2014年6月16日月曜日

[Project Euler] Problem 22 「名前のスコア」

5000個以上の名前が書かれている46Kのテキストファイル names.txt を用いる. まずアルファベット順にソートせよ.
のち, 各名前についてアルファベットに値を割り振り, リスト中の出現順の数と掛け合わせることで, 名前のスコアを計算する.

たとえば, リストがアルファベット順にソートされているとすると, COLINはリストの938番目にある. またCOLINは 3 + 15 + 12 + 9 + 14 = 53 という値を持つ. よってCOLINは 938 × 53 = 49714 というスコアを持つ.

ファイル中の全名前のスコアの合計を求めよ.
素直に解いていきます.
  1. アルファベットを数値に変換する手続きを定義する.
  2. string->listを使って文字列を文字のリストに変換し, 名前の値を計算する.
  3. name.txtを読み込むのも面倒なので, ソースコードに埋め込む.
  4. 名前のソートは, sort手続きを使う.
  5. mapとfoldを使って, 求める値を計算する.
手続きは次のとおりです. name.txtの内容については一部, 省略します.
(require srfi/1)

(define (alpha-value c)
  (cdr 
   (assoc c
          (map cons
               (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
               (iota 26 1)))))

(define (name-score name)
  (fold + 0 (map alpha-value (string->list name))))

(define name-list
  (sort (list
         "MARY" "PATRICIA" "LINDA" "BARBARA" "ELIZABETH" "JENNIFER" "MARIA" 
         "SUSAN" "MARGARET" "DOROTHY" "LISA" "NANCY" "KAREN" "BETTY" "HELEN"
         "SANDRA" "DONNA" "CAROL" "RUTH" "SHARON" "MICHELLE" "LAURA" "SARAH" 
         "KIMBERLY" "DEBORAH" "JESSICA" "SHIRLEY" "CYNTHIA" "ANGELA" "MELISSA" 

         ... 省略 ...

         "LUCIUS" "KRISTOFER" "BOYCE" "BENTON" "HAYDEN" "HARLAND" "ARNOLDO" "RUEBEN"
         "LEANDRO" "KRAIG" "JERRELL" "JEROMY" "HOBERT" "CEDRICK" "ARLIE" "WINFORD"
         "WALLY" "LUIGI" "KENETH" "JACINTO" "GRAIG" "FRANKLYN" "EDMUNDO" "SID"
         "PORTER" "LEIF" "JERAMY" "BUCK" "WILLIAN" "VINCENZO" "SHON" "LYNWOOD"
         "JERE" "HAI" "ELDEN" "DORSEY" "DARELL" "BRODERICK" "ALONSO"
         )
        string<?))

計算します.
ようこそ DrRacket, バージョン 5.3.3 [3m].
言語: Pretty Big; memory limit: 2048 MB.
> (fold + 
        0
        (map *
             (map name-score name-list)
             (iota (length name-list) 1)))
871198282
> 

0 件のコメント:

コメントを投稿