Mercurial > coderloop
view src/find_words.clj @ 0:307a81e46071 tip
initial committ
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 18 Oct 2011 01:17:49 -0700 |
parents | |
children |
line wrap: on
line source
1 (ns coderloop.find-words2 (:use [clojure.contrib def3 [seq :only [indexed]]4 [duck-streams :only [read-lines file-str]]]5 [clojure.java io]6 [rlm shell-inspect]))10 "I'm going to solve this using convolution because I like how the kernel11 looks for this problem. For each word, we build up an asterisk kernel12 like so:14 {:word \"Robert\"}15 kernel:17 t t t18 r r r19 e e e20 b b b21 ooo22 treboRobert23 ooo24 b b b25 e e e26 r r r27 t t t29 isn't it really cute-looking?31 Anyways, I'll drag these asterisks along the word-matrix via convolution32 and use them to build up a transient structure that contains only the matches.34 Then, I'll use that transitnt structure to remove all matches from the original35 grid.37 I need stuff to do convolutions, to make kernels given a word, to create the38 transient structure, and to remove the entries in the transient structure39 from the original word-grid. I also need a way to represent a word grid."41 (defvar strcat (partial apply str)42 "flattens a list by glomming everything together in a string.")44 (defn word-grid45 "create a mapping from elements in R^2 to chars"46 [words]47 (reduce48 merge49 (map (fn [[idx s]]50 (zipmap51 (map #(vector (first %) idx) (indexed s))52 (seq s)))53 (indexed words))))56 (defn bounding-square57 "finds the minimal square it takes to bound the grid. works for all58 geometries."59 [grid]60 (let [coords (keys grid)61 xs (sort (map first coords))62 ys (sort (map second coords))]63 [(first xs) (last xs) (first ys) (last ys)]))65 ;;I have no compunctinos with using mutable state in printing66 (defn print-grid* [grid]67 (let [[x-min x-max y-min y-max] (bounding-square grid)68 canvas (atom69 (vec (for [y (range (inc (- y-max y-min)))]70 (vec (repeat (inc (- x-max x-min)) ".")))))]71 (dorun (map (fn [[[x y] c]]72 (swap! canvas #(assoc-in % [ (- y y-min) (- x x-min)] c))) grid))73 @canvas))75 (defn print-grid76 "nice for debugging but irrelevant for the rest of the problem"77 [grid]78 (dorun79 (for [line (print-grid* grid)]80 (do (dorun (map print line))81 (println)))))83 (defn asterisk-kernel [word]84 (let [span (range (inc (count word)))]85 (vector86 (zipmap (map #(vector 0 %) span) word)87 (zipmap (map #(vector 0 (- %)) span) word)88 (zipmap (map #(vector % %) span) word)89 (zipmap (map #(vector % (- %)) span) word)90 (zipmap (map #(vector % 0) span) word)91 (zipmap (map #(vector (- %) 0) span) word)92 (zipmap (map #(vector (- %) %) span) word)93 (zipmap (map #(vector (- %) (- %)) span) word))))95 ;;this is not lazy :(96 (defn search-grid-at-point [kernel grid [point-x point-y]]97 (let [shift-kernel98 (zipmap99 (map (fn [[x y]]100 [(+ x point-x)101 (+ y point-y)])102 (keys kernel))103 (vals kernel))]104 (if (= (select-keys grid (keys shift-kernel))105 shift-kernel)106 shift-kernel nil)))108 (defn search-word-kernel109 "search the grid for a particular kernel and store the reusult in the110 atom (matches)"111 [grid kernel]112 (reduce merge (map (fn [point]113 (search-grid-at-point kernel grid point))114 (keys grid))))116 (defn search-word [grid word]117 (let [kernels (asterisk-kernel word)]118 (reduce merge (map #(search-word-kernel grid %) kernels))))120 (defn search-words [grid words]121 (reduce merge (map #(search-word grid %) words)))123 (defn remove-matches [grid matches]124 (apply (partial dissoc grid) (keys matches)))126 (defn grid->str [grid]127 (strcat (vals (apply sorted-map128 (interleave (map (comp vec reverse) (keys grid)) (vals grid))))))130 (defn read-wordsearch [#^java.io.File input]131 (let [[crossword words] (split-with (comp not (partial = "")) (read-lines input))132 words (rest words)]133 [crossword words]))135 (defn process-wordsearch [[crossword words]]136 (let [grid (word-grid crossword)]137 (grid->str (remove-matches grid (search-words grid words)))))139 (defn doit [args]140 (println141 (process-wordsearch142 (read-wordsearch143 (file-str (first args))))))145 ;;********************************************************************************146 (if (command-line?)147 (doit *command-line-args*))150 (def input (file-str "/home/r/coderloop-test/input.txt"))151 (def a (file-str "/home/r/coderloop-test/findwords-a.in"))152 (def d (file-str "/home/r/coderloop-test/findwords-d.in"))153 (def c (file-str "/home/r/coderloop-test/findwords-c.in"))154 (def e (file-str "/home/r/coderloop-test/findwords-e.in"))156 (def test-grid157 ["ELGOOGWWW"158 "TIRXMAHIR"159 "BATMANZNC"160 "CMRVLTOLD"])162 (def test-words163 ["MAIL"164 "WIN"165 "GOOGLE"166 "TAR"167 "BATMAN"168 "CAR"169 "WWW"170 "TOLD"171 "CD"])