Naomi's notebook

Naomi's notebook

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