Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Created May 3, 2022 18:08
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
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

@jonasseglare
Copy link

(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

(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

(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

(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