Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
Copy link

nbardiuk commented May 3, 2022

(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
Copy link

mchampine commented May 3, 2022

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
Copy link

steffan-westcott commented May 3, 2022

(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

jonasseglare commented May 4, 2022

(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
Copy link

miner commented May 5, 2022

(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

JonathanHarford commented May 6, 2022

(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

Altariarite commented May 10, 2022

(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

KingCode commented May 26, 2022

(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