Problem22

30分プログラム、その288。Problem22 via Project Euler

5000個以上の名前が書かれている46Kのテキストファイルnames.txt を用いる. まずアルファベット順にソートせよ.
のち, 各名前についてアルファベットに値を割り振り, リスト中の出現順の数と掛け合わせることで, 名前のスコアを計算する.
たとえば, リストがアルファベット順にソートされているとすると, COLINはリストの938番目にある. またCOLINは3 + 15 + 12 + 9 + 14 = 53という値を持つ. よってCOLINは938 × 53 = 49714というスコアを持つ.
ファイル中の全名前のスコアの合計を求めよ.

アルファベットと値の対応がいまひとつ分からない。C=3、O=15から想像して、A=1、B=2、C=3、...ということにした。あとリストは0番目からではなく1番目から数えることにした。
names.txtは

"MARY","PATRICIA","LINDA",...

のような形式をしているので、一行のCSVファイルということにしてgauche.csvで読み込んでいる。

使い方

$ time gosh problem22.scm names.txt
871198282
gosh problem22.scm names.txt  0.55s user 0.05s system 88% cpu 0.677 total

ソースコード

#! /opt/local/bin/gosh
;; -*- mode:scheme; coding:utf-8 -*-
;;
;; problem22.scm -
;;
;; Copyright(C) 2008 by mzp
;; Author: MIZUNO Hiroki / mzpppp at gmail dot com
;; http://howdyworld.org
;;
;; Timestamp: 2008/04/16 23:06:13
;;
;; This program is free software; you can redistribute it and/or
;; modify it under MIT Lincence.
;;

(use text.csv)
(use srfi-1)
(use gauche.sequence)

(define read-csv (make-csv-reader #\,))
(define (sum xs) (fold + 0 xs))
(define (char->point c)
  (- (char->integer c) (char->integer #\A) -1))
(define (name->point name)
  (sum (map char->point name)))

(define (main args)
  (let1 names (call-with-input-file (cadr args) 
		(lambda (port) (read-csv port)))
    (print (sum (map-with-index (lambda (i name) 
				  ; (print i ":" name ":" (name->point name))
				  (* (+ i 1) (name->point name)))
				(sort names))))))