Created
December 11, 2012 08:29
-
-
Save msgodf/4256920 to your computer and use it in GitHub Desktop.
Clojure solution to to "Radiation Search" problem on check.io
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
(ns cluster.core) | |
; Begin by creating 'clusters' for all the squares of a particular number | |
; Then repeatedly check for adjacent clusters and merge them | |
(defn random-grid | |
"A grid composed of random values in range [1,n]" | |
[size n] | |
(vec (map vec | |
(partition size | |
(repeatedly (* size size) | |
#(int (+ 1.5 (rand (dec n))))))))) | |
(def grid1to5 | |
(random-grid 10 5)) | |
(defn grid-clusters | |
"The coordinates of the n's within the grid" | |
[grid size n] | |
(apply vector | |
(map vector | |
(remove nil? | |
(for [x (range size) | |
y (range size)] | |
(when (= n (get-in grid [y x])) | |
[x y])))))) | |
(defn max-value-in-grid | |
[grid] | |
(apply max | |
(map #(apply max %) | |
grid))) | |
(defn max-with-index | |
[coll] | |
(apply max-key | |
val | |
(zipmap (range (count coll)) | |
coll))) | |
(defn inc-index | |
[[a b]] | |
[(inc a) b]) | |
(defn int-pairs | |
"Generate all sets of integers pairs in [0,n), excluding those of the form [a a]" | |
[n] | |
(mapcat #(map vector | |
(repeat %) | |
(range (inc %) n)) | |
(range n))) | |
(defn adjacent? | |
"Given two pairs of (x,y) coordinates, checks whether they are adjacent to each other" | |
[[x1 y1] [x2 y2]] | |
(or (and (= y1 y2) | |
(or (= x1 (inc x2)) | |
(= x1 (dec x2)))) | |
(and (= x1 x2) | |
(or (= y1 (inc y2)) | |
(= y1 (dec y2)))))) | |
(defn clusters-adjacent? | |
"Check whether at least one point in the first cluster is adjacent to another in the other cluster" | |
[a b] | |
(some true? | |
(for [first-point a | |
second-point b] | |
(adjacent? first-point second-point)))) | |
(defn remove-nth | |
"Removes the item specified by the index" | |
[coll index] | |
(mapcat vec [(take index coll) | |
(drop (inc index) coll)])) | |
(defn merge-clusters | |
"Replaces the first cluster by it merged with the second cluster, then removes the second cluster" | |
[clusters first-index second-index] | |
(vec (remove-nth (assoc clusters | |
first-index | |
(apply merge | |
(clusters first-index) | |
(clusters second-index))) | |
second-index))) | |
(defn first-adjacent-clusters | |
"Check all pairs of clusters, and returns the first pair that are adjacent, or nil if none are adjacent" | |
[clusters] | |
(first (remove nil? | |
(for [[a b] (int-pairs (count clusters))] | |
(when (clusters-adjacent? (clusters a) | |
(clusters b)) | |
[a b]))))) | |
(defn check-and-merge | |
"The core of the program, checks for adjacent clusters and merges them" | |
[c] | |
(loop [clusters c] | |
(if-let [[a b] (first-adjacent-clusters clusters)] | |
(recur (merge-clusters clusters a b)) | |
clusters))) | |
(defn biggest-cluster | |
"Find the number that has the biggest cluster within the grid" | |
[grid] | |
(let [n (max-value-in-grid grid) | |
size (count (grid 0))] | |
(inc-index | |
(max-with-index | |
(map #(apply max | |
(map count | |
(check-and-merge (grid-clusters grid size %)))) | |
(range 1 (inc n))))))) | |
(defn -main | |
"Create a random grid and output the biggest cluster" | |
[& args] | |
(let [grid (random-grid (Integer/parseInt (nth args 0)) | |
(Integer/parseInt (nth args 1)))] | |
(do | |
(println (map #(clojure.string/join (concat (map str %) "\n")) grid)) | |
(biggest-cluster grid)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment