ここのところ、ブログに載せるのをさぼっていたので、連投です。
79は、暗唱番号の問題です。
よくある、手元の表から何番目と何番目と何番目を答えてみたいなやつの問題。
答の列から元の表を推測します。
とりあえず、と、思って「答の列で最も左にあるやつが元の表でも左にあるでしょう」っていう方式で解いてみたら解けちゃった。
142 813 827 なら、8が一番左。 で、8を取り除いて、
142 13 27 なら、1が一番左。という方式。
でも、出現頻度に差があるので、「先頭に多く現れるもの」でなく、「先頭以外により現れないもの」を選択するのがミソ。
でも、次の42 3 27 みたいに、4 か 3。 のようになってしまうかなぁ。 そしたら考え直しだなぁ、と思っていたんだけど、そうはならなかった。
・input-data
問題のデータを読み込んで、数値のリストのリストにしています。
((1 2 9) (1 6 0) (1 6 2) ...
・collect-stat
受け取ったデータからそれぞれの数字の度数分布を計算します。
{7 (13 0 0), 3 (7 2 0), 8 (1 6 5), ...
この場合、7は最初のみに13回、3 は最初に7回で2桁目に2回、 8は最初に1回、2桁目に6回、3あ桁目に5回 現れたということです。
・remove-left
数値のリスト内の各リストの先頭にnがあれば取り除きます。
・select-left
度数分布のリストの中から、2桁目以降での出現度数の最も小さいものを選びます。
sorted-mapを使ってみた。
ほんとは、collect-stat の初期データの {} をsorted-mapにできればいいんだけど、やりかたがあわからん。
そもそも、この、sorted-map-byの引数の与えたかたがとっても気に入らない。 スコープの外にあるように見える、stat-dataを使ってるでしょ?。なんで?
・pe79
最初のデータから左を取り除くのをくりかえして、なくなるまでやる。
79は、暗唱番号の問題です。
よくある、手元の表から何番目と何番目と何番目を答えてみたいなやつの問題。
答の列から元の表を推測します。
とりあえず、と、思って「答の列で最も左にあるやつが元の表でも左にあるでしょう」っていう方式で解いてみたら解けちゃった。
142 813 827 なら、8が一番左。 で、8を取り除いて、
142 13 27 なら、1が一番左。という方式。
でも、出現頻度に差があるので、「先頭に多く現れるもの」でなく、「先頭以外により現れないもの」を選択するのがミソ。
でも、次の42 3 27 みたいに、4 か 3。 のようになってしまうかなぁ。 そしたら考え直しだなぁ、と思っていたんだけど、そうはならなかった。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Problem 79 : 2012/4/20 | |
;; "Elapsed time: 9.488646 msecs" | |
(require '[clojure.string :as str]) | |
(defn num-to-list [num] | |
(map #(Character/digit % 10) (str num))) | |
(def input-data | |
(map (fn [s] (map #(Character/digit % 10) (seq s))) | |
(sort (distinct (str/split-lines (slurp "src/pe13/keylog.txt")))))) | |
(defn collect-stat [num-list] | |
(reduce (fn [m [a b c]] | |
(-> m | |
(assoc ,, a (map + (get m a [0 0 0]) [1 0 0])) | |
(assoc ,, b (map + (get m b [0 0 0]) [0 1 0])) | |
(assoc ,, c (map + (get m c [0 0 0]) [0 0 1])))) | |
{} num-list)) | |
(defn remove-left [n num-list] | |
(filter identity (map #(if (= (first %) n) (next %) %) num-list))) | |
(defn select-left [stat-data] | |
(first (first | |
(into (sorted-map-by (fn [k1 k2] | |
(< (reduce + (next (get stat-data k1))) | |
(reduce + (next (get stat-data k2)))))) | |
stat-data)))) | |
(defn pe79 [] | |
(loop [data input-data res []] | |
(if (empty? data) | |
res | |
(let [leftmost (select-left (collect-stat data))] | |
(recur (remove-left leftmost data) (conj res leftmost)))))) |
・input-data
問題のデータを読み込んで、数値のリストのリストにしています。
((1 2 9) (1 6 0) (1 6 2) ...
・collect-stat
受け取ったデータからそれぞれの数字の度数分布を計算します。
{7 (13 0 0), 3 (7 2 0), 8 (1 6 5), ...
この場合、7は最初のみに13回、3 は最初に7回で2桁目に2回、 8は最初に1回、2桁目に6回、3あ桁目に5回 現れたということです。
・remove-left
数値のリスト内の各リストの先頭にnがあれば取り除きます。
・select-left
度数分布のリストの中から、2桁目以降での出現度数の最も小さいものを選びます。
sorted-mapを使ってみた。
ほんとは、collect-stat の初期データの {} をsorted-mapにできればいいんだけど、やりかたがあわからん。
そもそも、この、sorted-map-byの引数の与えたかたがとっても気に入らない。 スコープの外にあるように見える、stat-dataを使ってるでしょ?。なんで?
・pe79
最初のデータから左を取り除くのをくりかえして、なくなるまでやる。
0 コメント:
コメントを投稿