Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Created May 3, 2022 18:08
Show Gist options
  • Select an option

  • Save ericnormand/598b0fc7aea99b628cfc7120857dc7df to your computer and use it in GitHub Desktop.

Select an option

Save ericnormand/598b0fc7aea99b628cfc7120857dc7df to your computer and use it in GitHub Desktop.
467 Eric Normand Newsletter

Unfriendly neighors

Let's say we have a sequence of integers:

[1 3 2 4 1]

There are 4 spots between numbers where we could insert a new number (represented by commas):

[1 ,, 3 ,, 2 ,, 4 ,, 1]
;; ^    ^    ^    ^
;; |    |    |    spot 3.5, between 3 and 
;; |    |    spot 2.5, between 2 and 3
;; |    spot 1.5, between 1 and 2
;; spot 0.5, between 0 and 1

We can represent those spots as halves, such as 0.5.

We only want to insert numbers when they are "happy". Odd numbers are happy when we insert them next to at least one odd number. Even numbers are happy when we insert them next to at least one even number.

Write a function that takes a sequence of integers and an integer. It should return the happy spots and the unhappy spots.

(spots [1 1]     1) ;=> {:happy [0.5]                   }
(spots [1 1]     2) ;=> {                 :unhappy [0.5]}
(spots [1 1 2]   4) ;=> {:happy [1.5]     :unhappy [0.5]}
(spots [1 1 2 2] 3) ;=> {:happy [0.5 1.5] :unhappy [2.5]}

Note: Inserting a number may make pre-existing numbers unhappy. Ignore them!

Thanks to this site for the problem idea, where it is rated Very Hard in Ruby. The problem has been modified.

Please submit your solutions as comments on this gist.

To subscribe: https://ericnormand.me/newsletter

@nbardiuk

nbardiuk commented May 3, 2022

Copy link
Copy Markdown
(defn spots [numbers candidate]
  (let [good-neighbor? (if (odd? candidate) odd? even?)
        pairs (partition 2 1 numbers)
        spots (range 0.5 (count numbers))]
    (->> (for [[neighbors spot] (map vector pairs spots)]
           (if (some good-neighbor? neighbors)
             {:happy [spot]}
             {:unhappy [spot]}))
         (reduce (partial merge-with into)))))

@mchampine

mchampine commented May 3, 2022

Copy link
Copy Markdown

First cut, quick and dirty

(defn happy? [c [_ pr]] (if (even? c) (some even? pr) (some odd? pr)))

(defn spots [lst cand]
  (let [mi (map-indexed #(vector (+ 0.5 %1) %2) (partition 2 1 lst))
        ha (mapv first (filter (partial happy? cand) mi))
        uha (mapv first (remove (partial happy? cand) mi))
        s1 (if (seq ha) (assoc {} :happy ha) {})]
    (if (seq uha) (assoc s1 :unhappy uha) s1)))

golfed version

(defn spots [lst cand]
  (let [happy? (fn [[_ pr]] (if (even? cand) (some even? pr) (some odd? pr)))
        mi (map-indexed #(vector (+ 0.5 %1) %2) (partition 2 1 lst))]
    (remove #(empty? (val %))
            {:happy (mapv first (filter happy? mi))
             :unhappy (mapv first (remove happy? mi))})))

@steffan-westcott

steffan-westcott commented May 3, 2022

Copy link
Copy Markdown
(defn spots [xs n]
  (let [m (->> (map #(even? (+ n %)) xs)
               (partition 2 1)
               (map #(if (some identity %) :happy :unhappy))
               (map vector (iterate inc 0.5))
               (group-by second))]
    (update-vals m #(map first %))))

@jonasseglare

Copy link
Copy Markdown
(defn spots [elements x]
  (apply merge-with into 
         (for [[w f] [[:happy true] [:unhappy]]
               [a b & r] (iterate rest elements)
               :while b :when (= f (some #(even? (+ x %)) [a b]))]
           {w [(- (count elements) (count r) 1.5)]})))

@miner

miner commented May 5, 2022

Copy link
Copy Markdown
(defn spots [xs x]
  (let [test? (if (odd? x) odd? even?)
        xv (if (vector? xs) xs (into [] xs))]
    (reduce (fn [m i]
              (let [k (if (or (test? (xv i)) (test? (xv (inc i)))) :happy :unhappy)]
                (assoc m k (conj (m k []) (+ i 0.5)))))
            {}
            (range (dec (count xv))))))

@JonathanHarford

Copy link
Copy Markdown
(defn spots [neighborhood neighbor]
  (->> neighborhood
       (map #(even? (+ neighbor %)))
       (partition 2 1)
       (map-indexed (fn [i [x y]]
                      {(if (or x y) :happy :unhappy) [(+ 0.5 i)] }))
       (apply merge-with concat)))

@Altariarite

Copy link
Copy Markdown
(defn happy?
  "odd/even: happy with at least one odd/even"
  [neighbours num]
  (cond
    (and (even? num) (some even? neighbours)) :happy
    (and (odd? num) (some odd? neighbours)) :happy
    :else :unhappy))

(defn spots
  "takes a sequence of integers and an integer. return the happy spots and the unhappy spots."
  [seq num]
  (->>
   (partition 2 1 seq)
   (map-indexed (fn [idx e]
                  {(happy? e num) [(+ 0.5 idx)]}))
   (apply merge-with into)))

@KingCode

Copy link
Copy Markdown
(defn spots [xs n]
  (let [pred (if (odd? n) odd? even?)]
    (->> xs (partition 2 1)
         (map-indexed vector)
         (reduce (fn [m [i part]]
                   (update m (if (some pred part)
                               :happy
                               :unhappy)
                           conj 
                           (+ i 0.5)))
                 {:happy [] :unhappy []}))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment