Euler: Problem 103

Posted by YpsilonTAKAI On 2020年3月14日土曜日 0 コメント
去年の末に解いたやつです。

条件に合う数列を新しく作る問題

これ、かなり悩んだ。 102を解いたあと、すぐに手を付けたんだけど、解きかたわからず/思いつかずで、放置している間に数年経ってしまった。
まあ<結局、初期の頃に思いついた、「全部やってみる」方式で解いてみることにして、実際やってみたら、時間はたいしてかからなかったという。

- 真ん中の数字を先頭にして新しい数列を作る
- 含まれる数を前後にいくつかずらした数列を全て生成
- 昇順になっていないものを除外

これで、候補を作って、条件に合うかどうかチェックというやりかた。

(ns euler.pe_103
(:require [clojure.math.combinatorics :as combo]))
;; Prablem 103
;; "Elapsed time: 5387.0654 msecs"
;; rule 1: S(B) != S(C)
(defn verify-rule-1 [target-set]
(->> (combo/subsets target-set)
(map #(apply + %) ,,)
((juxt #(count %) #(count (set %))) ,,)
(apply = ,,)))
;; rule 2: S(B) > S(C)
(defn verify-rule-2 [target-set]
(let [center-num (quot (+ 1 (count target-set)) 2)
front-half (take center-num target-set)
tail-half-1 (drop (+ center-num (if (even? (count target-set)) 1 0)) target-set)]
(> (apply + front-half)
(apply + tail-half-1))))
;; create next level near optimal sequence
(defn middle-element [target-set]
(let [half (/ (count target-set) 2)
center-pos (if (int? half) half (int (- half 0.5)))]
(nth target-set center-pos)))
(defn next-level-s [prev-s]
(let [center (middle-element prev-s)
new (vec (conj (map #(+ center %) prev-s) center))]
new))
;; create all candidate sequence list with depth 'level'
(defn all-candidate [s level]
(->> s
(mapv #(vec (range (- % level) (+ % level 1))) ,,)
(apply combo/cartesian-product ,,)))
;; check if it meet the criteria
(defn matched-seq? [s]
(and (apply < s)
(verify-rule-2 s)
(verify-rule-1 s)))
;; search next level optimal sequence with window 'expand-level
(defn find-next-optimal-list [current-s expand-level]
(let [next-near-optimal-list (next-level-s current-s)]
(->> (for [s (all-candidate next-near-optimal-list expand-level)]
(if (matched-seq? s) s))
(remove nil? ,,)
(sort-by #(apply + %) ,,)
(#(vector (apply + (first %)) (first %) ,,)))))
view raw pe_103.clj hosted with ❤ by GitHub

0 コメント:

コメントを投稿