AtCoder Beginners Selection in Clojure
Clojureのサンプルコードを見ていたらHaskellっぽくて面白そうだったのでやります。ちなみに今はじめて見た言語です。
難しそう
コードは短くなる努力は特段しませんが、まあまあ短くスッキリさせることは意識して書きます。
参考にしたサイト
clojure.core namespace | ClojureDocs - Community-Powered Clojure Documentation and Examples
導入に
一時間で覚えるClojure - None is None is None
多言語のサンプルコード集
説明のないとってもシンプルなサンプルプログラム集
これとても便利で、 ABSくらいならこのサイトを見ればなんとかいける気がする
過去の記事
naomi-notebook.hatenablog.com
naomi-notebook.hatenablog.com
naomi-notebook.hatenablog.com
naomi-notebook.hatenablog.com
naomi-notebook.hatenablog.com
PracticeA - Welcome to AtCoder
(println (+ (read) (read) (read)) (read))
ABC086A Product
(println (if (= (mod (* (read) (read)) 2) 0) "Even" "Odd"))
ABC081A Placing Marbles
そういえば関数型言語なので代入とかがめんどくさいですね(let)
というわけでワンライナーしてしまう方針になります(競プロ的には良いけど実務的にはよくなさそう)
(println (count (re-seq #"1" (read-line))) )
ABC081B Shift only
関数型言語、入力も繰り返してしまいがちなのでこういう問題はrubyみたいに短縮しにくいかも 多分工夫すればできると思うけど
というわけで再帰を使ったループをしました 関数型言語は楽しいなあ
(def N (read)) (def A (for [i (range N)] (read))) (defn for-shift [x] (if (= (mod x 2) 0) (+ 1 (for-shift (quot x 2))) 0)) (println (reduce min (map for-shift A )))
ABC087B Coins
( let [A (read) B (read) C (read) X (quot (read) 50)]( println (reduce + ( for [i (range (+ 1 A)) j (range (+ 1 B)) k (range (+ 1 C))] ( if (= (+ (* i 10) (* j 2) k) X) 1 0 )))))
ABC083B Some Sums
リスト内包表記難しくない?
料理本: 3.4. リスト内包表記を使いたい - tnoda-clojure
- when と
- let が便利。
(defn sum-of-digit [x] (if (> x 0) (+ (mod x 10) (sum-of-digit (quot x 10))) 0)) (def N (read))(def A (read))(def B (read)) (println (reduce + (for [x (range (+ 1 N)) :let [s (sum-of-digit x)] :when (and (>= s A) (<= s B))] x) ))
ABC088B Card Game for Two
いいサイト見つけた
イディオム集 — Clojure の日本語ガイド
料理本: 3.4. リスト内包表記を使いたい - tnoda-clojure
(def N (read)) (def A (sort > (for [x (range N)] (read)))) (println (reduce + (for [[i x] (map-indexed vector A)] (* (if (even? i) 1 -1) x))))
ABC085B Kagami Mochi
短い!
(println (count (distinct (for [x (range (read))] (read)))))
ABC085C Otoshidama
数字は、(str i j k...)でそのままStringにキャストできる。
あとで調べたら、(string/join ", " [1 2 3])でもリストの内容を列挙したStringを制作できる。
(def N (read))(def Y (quot (read) 1000)) (def lis (for [i (range (inc N)) j (range (inc (- N i))) :let [k (- N (+ i j))] :when (= (+ (* i 10) (* j 5) (- N (+ i j))) Y) ] [i j k] )) (println (if (> (count lis) 0) (let [ [i j k] (first lis)] (str i " " j " " k)) "-1 -1 -1"))
ABC049C 白昼夢 / Daydream
これでいけるはず(手元では正解する)のに通らない。明らかに正しそうなので誰か教えてください
(println (if (nil? (re-find #"^(eraser?|dream(er)?)+$" (read-line))) "NO" "YES"))
ABC086C Traveling
一つ前の要素にアクセスするのがなかなか難しかった。
[Clojure] ちょっと難しいシーケンス処理 - /home/matstani/weblog
このサイトを参考にして、restで一つずらしたリストを作りそことの差分をとった。
でもTLEになってしまった。計算量のオーダーNで10^5くらいだと思うんですが、それだと前の問題が通らないはずなのでうーん?わからないです
(def N (read)) (def lis (cons [0 0 0] (for [i (range N)] [(read) (read) (read)]))) (println (if (= N (count (for [[dt dx dy] (map #(map - %1 %2) (rest lis) lis) :let [d (- dt (+ (Math/abs dx) (Math/abs dy)))] :when (and (>= d 0) (even? d))] dt))) "Yes" "No"))
これでちょっとだけ早くなった(まだTLEがある)
(def N (read)) (def lis (cons [0 0 0] (for [i (range N)] [(read) (read) (read)]))) (def relis (rest lis)) (println (if (= N (count (for [[dt dx dy] (map #(map - %1 %2) relis lis) :let [d (- dt (+ (Math/abs dx) (Math/abs dy)))] :when (and (>= d 0) (even? d))] dt))) "Yes" "No"))
少し早くなったけどまだTLE(どうやら rest関数はかなり時間がかかるっぽい、普通にやればオーダーNだと思うのですが…)
(def N (read)) (def lis (cons [0 0 0] (for [i (range N)] [(read) (read) (read)]))) (def relis (rest lis)) (def dlis (map #(map - %1 %2) relis lis) ) (println (if (empty? (for [[dt dx dy] dlis :let [d (- dt (+ (Math/abs dx) (Math/abs dy)))] :when (or (< d 0) (odd? d))] dt)) "Yes" "No"))
loop/recurの方が早いらしいけど、書き方がよくわかりません…
お願い
最後の二問が結構適当になってしまったのですが、通している人のコードを見てもわたしのどこが悪かったのかわからなかったので、時間もないのでとりあえずおいておきます
誰か教えてくださると嬉しいです!(特に白昼夢 / DaydreamのREはよくわからない)
白昼夢
Submission #6396059 - AtCoder Beginners Selection
Traveling
Submission #6396507 - AtCoder Beginners Selection