PasteRack.org
Paste # 5803
2025-12-26 07:42:01

Fork as a new paste.

Paste viewed 233 times.


Embed:

logic bombs logic 2

  1. #lang racket
  2. ;; logic bombs 137
  3. ;; idk how to get going with this puzzle so I guess it's time to learn racklog https://docs.racket-lang.org/racklog/
  4.  
  5. (module possible-hits racket
  6.   (provide possible-sums possible-hit-set possible-hits)
  7.  
  8.   (module+ test
  9.     (require rackunit)
  10.     (define-syntax-rule (test-possible-sums? NAME INPUT EXPECTED)
  11.       (test-equal? NAME (possible-sums INPUT) EXPECTED))
  12.     (define-syntax-rule (test-possible-hit-set? NAME INPUT EXPECTED)
  13.       (test-equal? NAME (possible-hit-set INPUT) EXPECTED)))
  14.  
  15.   ;; given a list of numbers/options for numbers (as a list) return set of all possible sums of subsets of those numbers
  16.   ;; e.g. (possible-sums '(1 2 3)) => (set 0 1 2 3 4 5 6)
  17.   ;; when an option is given, use one of but not multiple of the alternatives
  18.   ;; e.g. (possible-sums '(1 {10 20})) => (set 0 1 20 21 10 11)
  19.   (define (possible-sums single-can-see)
  20.     (if (empty? single-can-see)
  21.         (set 0)
  22.         (let loop ([current (car single-can-see)]
  23.                    [rest (cdr single-can-see)]
  24.                    [found (set 0)])
  25.           (let* ([subsums (possible-sums rest)]
  26.                  [newfound (cond [(list? current)
  27.                                   (apply set-union
  28.                                          (for/list ([current-option current])
  29.                                            (list->set (set-map subsums (λ (n) (+ current-option n))))))]
  30.                                  [else
  31.                                   (list->set (set-map subsums (λ (n) (+ current n))))])]
  32.                  [allfound (set-union found newfound)])
  33.             (if (empty? rest) allfound
  34.                 (loop (car rest) (cdr rest) allfound))))))
  35.  
  36.   (module+ test
  37.     (test-possible-sums? "Can always get 0" '() (set 0))
  38.     (test-possible-sums? "Basic with sum" '(1 2) (set 0 1 2 3))
  39.     (test-possible-sums? "Alternative can't sum" '({1 2}) (set 0 1 2))
  40.     (test-possible-sums? "Multiple alternatives" '({1 2} {10 20}) (set 0 1 2 10 20 11 21 12 22)))
  41.  
  42.   ;; given a list of what each bomb of the same type can see, return set of
  43.   ;; possible target values for that type of bomb (see possible-sums above or test cases for input format)
  44.   (define (possible-hit-set can-see)
  45.     (if (empty? can-see) (set 0)
  46.         (apply set-intersect (map possible-sums can-see))))
  47.  
  48.   ;; helper producing a list instead of a set
  49.   (define possible-hits (compose set->list possible-hit-set))
  50.  
  51.  
  52.   (module+ test
  53.     (test-possible-hit-set? "x example"
  54.                             '[(1 2 3)
  55.                               (3 1 2)]
  56.                             (set 0 1 2 3 4 5 6))
  57.     (test-possible-hit-set? "y example"
  58.                             '[(3 3 3)
  59.                               (3 1 {1 2})
  60.                               (3 3 3)
  61.                               (1 2 2)]
  62.                             (set 0 3))
  63.     (test-possible-hit-set? "z example"
  64.                             '[({1 2} 1 3)
  65.                               (1 3 3)
  66.                               ({1 2} 1 2)]
  67.                             (set 0 1 3 4))
  68.     (test-possible-hit-set? "a example"
  69.                             '[(3 1 {1 2})]
  70.                             (set 0 1 2 3 4 5 6))
  71.     (test-possible-hit-set? "b example"
  72.                             '[(3 3 1)]
  73.                             (set 0 1 3 4 6 7))
  74.     (test-possible-hit-set? "c example"
  75.                             '[(2 3 1)]
  76.                             (set 0 1 2 3 4 5 6))
  77.  
  78.     (test-possible-hit-set? "can't see anything" '[] (set 0))))
  79.  
  80. (require racklog)
  81. (require 'possible-hits)
  82.  
  83. ;; how many of a type of bomb are there?
  84. (define %bomb-count %empty-rel)
  85.  
  86. ;; how many targets can each bomb of a type see?
  87. (define %can-see %empty-rel)
  88.  
  89. ;; can a bomb hit given number of targets?
  90. (define %can-hit
  91.   (%rel (bomb n can-see can-hit)
  92.         [(bomb n)
  93.          (%can-see bomb can-see)
  94.          (%is can-hit (possible-hits can-see))
  95.          (%member n can-hit)]))
  96.  
  97. ;; if a type of bomb hits a number of targets, how many total do all bombs of that type hit?
  98. (define %bomb-total
  99.   (%rel (bomb hit total-hit count)
  100.         [(bomb hit total-hit)
  101.          (%bomb-count bomb count)
  102.          (%is total-hit (* hit count))]))
  103.  
  104. ;; %true if list has no repeated elements
  105. (define %distinct
  106.   (%rel (l h t)
  107.         [('()) %true]
  108.         [((cons h t))
  109.          (%not (%member h t))
  110.          (%distinct t)]))
  111.  
  112. ;; for a list of bombs and a list of how many targets that type of bomb hits, how many total targets are hit?
  113. (define %combined-total
  114.   (%rel (bombs hits total totals)
  115.         [(bombs hits total)
  116.          (%andmap %bomb-total bombs hits totals)
  117.          (%is total (apply + totals))]))
  118.  
  119. ;; number of targets, list of bombs, list of hits each bomb does
  120. (define %hits
  121.   (%rel (target-count bombs hits totals)
  122.         [(target-count bombs hits)
  123.          (%andmap %can-hit bombs hits)
  124.          (%distinct hits)
  125.          (%combined-total bombs hits target-count)]))
  126.  
  127. ;;;;;;;;;;;;;;;; solve it ;;;;;;;;;;;;;;;;
  128.  
  129. (%assert! %bomb-count ()
  130.           [('x 2)]
  131.           [('y 4)]
  132.           [('z 3)]
  133.           [('a 1)]
  134.           [('b 1)]
  135.           [('c 1)])
  136. (%assert! %can-see ()
  137.           [('x '[(3 1 2)
  138.                  (3 1 2)])]
  139.           [('y '[(3 3 3)
  140.                  (3 1 {1 2})
  141.                  (3 3 3)
  142.                  (1 2 2)])]
  143.           [('z '[({1 2} 1 3)
  144.                  (1 3 3)
  145.                  ({1 2} 1 2)])]
  146.           [('a '[(3 1 {1 2})])]
  147.           [('b '[(3 3 1)])]
  148.           [('c '[(2 1 3)])])
  149.  
  150. (displayln "All possible combinations from start of puzzle:")
  151. (%find-all (x y z a b c)
  152.            (%hits 34 '(x y z a b c) (list x y z a b c)))
  153. (displayln "")
  154. (displayln "Remove impossible options for %can-see:")
  155. (define-syntax-rule (%clear-rel! REL)
  156.   (set! REL %empty-rel))
  157. (%clear-rel! %can-see)
  158. (%assert! %can-see ()
  159.           [('x '[(3 2)
  160.                  (3 1 2)])]
  161.           [('y '[(3 3 3)
  162.                  (3 1 {1 2})
  163.                  (3 3 3)
  164.                  (1 2 2)])]
  165.           [('z '[({1 2} 1 3)
  166.                  (1 3)
  167.                  ({1 2} 2)])]
  168.           [('a '[(3 1 {1 2})])]
  169.           [('b '[(3 3 1)])]
  170.           [('c '[(2 1 3)])])
  171. (%find-all (x y z a b c)
  172.            (%hits 34 '(x y z a b c) (list x y z a b c)))
  173. (displayln "")
  174. (displayln "Constrain hit counts where possible:")
  175. (%find-all (x y z a b c)
  176.            (%and (%hits 34
  177.                         '(x y z a b c)
  178.                         (list x y z a b c))
  179.                  (%>= x 2)
  180.                  (%>= y 3)
  181.                  (%>= z 1)
  182.                  (%>= a 2)
  183.                  (%>= c 2)))

=>

All possible combinations from start of puzzle:

'(((x . 6) (y . 3) (z . 1) (a . 5) (b . 0) (c . 2))

  ((x . 6) (y . 3) (z . 1) (a . 2) (b . 0) (c . 5))

  ((x . 6) (y . 3) (z . 0) (a . 5) (b . 4) (c . 1))

  ((x . 6) (y . 3) (z . 0) (a . 5) (b . 1) (c . 4))

  ((x . 6) (y . 3) (z . 0) (a . 4) (b . 1) (c . 5))

  ((x . 6) (y . 3) (z . 0) (a . 2) (b . 7) (c . 1))

  ((x . 6) (y . 3) (z . 0) (a . 1) (b . 7) (c . 2))

  ((x . 6) (y . 3) (z . 0) (a . 1) (b . 4) (c . 5))

  ((x . 6) (y . 0) (z . 4) (a . 5) (b . 3) (c . 2))

  ((x . 6) (y . 0) (z . 4) (a . 2) (b . 7) (c . 1))

  ((x . 6) (y . 0) (z . 4) (a . 2) (b . 3) (c . 5))

  ((x . 6) (y . 0) (z . 4) (a . 1) (b . 7) (c . 2))

  ((x . 6) (y . 0) (z . 3) (a . 5) (b . 7) (c . 1))

  ((x . 6) (y . 0) (z . 3) (a . 4) (b . 7) (c . 2))

  ((x . 6) (y . 0) (z . 3) (a . 2) (b . 7) (c . 4))

  ((x . 6) (y . 0) (z . 3) (a . 1) (b . 7) (c . 5))

  ((x . 5) (y . 3) (z . 1) (a . 2) (b . 7) (c . 0))

  ((x . 5) (y . 3) (z . 1) (a . 0) (b . 7) (c . 2))

  ((x . 5) (y . 3) (z . 0) (a . 6) (b . 4) (c . 2))

  ((x . 5) (y . 3) (z . 0) (a . 4) (b . 7) (c . 1))

  ((x . 5) (y . 3) (z . 0) (a . 4) (b . 6) (c . 2))

  ((x . 5) (y . 3) (z . 0) (a . 2) (b . 6) (c . 4))

  ((x . 5) (y . 3) (z . 0) (a . 2) (b . 4) (c . 6))

  ((x . 5) (y . 3) (z . 0) (a . 1) (b . 7) (c . 4))

  ((x . 5) (y . 0) (z . 4) (a . 3) (b . 7) (c . 2))

  ((x . 5) (y . 0) (z . 4) (a . 2) (b . 7) (c . 3))

  ((x . 5) (y . 0) (z . 3) (a . 6) (b . 7) (c . 2))

  ((x . 5) (y . 0) (z . 3) (a . 2) (b . 7) (c . 6))

  ((x . 4) (y . 3) (z . 1) (a . 6) (b . 0) (c . 5))

  ((x . 4) (y . 3) (z . 1) (a . 5) (b . 6) (c . 0))

  ((x . 4) (y . 3) (z . 1) (a . 5) (b . 0) (c . 6))

  ((x . 4) (y . 3) (z . 1) (a . 0) (b . 6) (c . 5))

  ((x . 4) (y . 3) (z . 0) (a . 6) (b . 7) (c . 1))

  ((x . 4) (y . 3) (z . 0) (a . 5) (b . 7) (c . 2))

  ((x . 4) (y . 3) (z . 0) (a . 2) (b . 7) (c . 5))

  ((x . 4) (y . 3) (z . 0) (a . 1) (b . 7) (c . 6))

  ((x . 2) (y . 3) (z . 4) (a . 5) (b . 1) (c . 0))

  ((x . 2) (y . 3) (z . 4) (a . 5) (b . 0) (c . 1))

  ((x . 2) (y . 3) (z . 4) (a . 1) (b . 0) (c . 5))

  ((x . 2) (y . 3) (z . 4) (a . 0) (b . 1) (c . 5))

  ((x . 2) (y . 3) (z . 1) (a . 6) (b . 4) (c . 5))

  ((x . 2) (y . 3) (z . 1) (a . 5) (b . 6) (c . 4))

  ((x . 2) (y . 3) (z . 1) (a . 5) (b . 4) (c . 6))

  ((x . 2) (y . 3) (z . 1) (a . 4) (b . 6) (c . 5))

  ((x . 2) (y . 3) (z . 0) (a . 6) (b . 7) (c . 5))

  ((x . 2) (y . 3) (z . 0) (a . 5) (b . 7) (c . 6))

  ((x . 2) (y . 0) (z . 4) (a . 6) (b . 7) (c . 5))

  ((x . 2) (y . 0) (z . 4) (a . 5) (b . 7) (c . 6))

  ((x . 1) (y . 3) (z . 4) (a . 6) (b . 0) (c . 2))

  ((x . 1) (y . 3) (z . 4) (a . 2) (b . 6) (c . 0))

  ((x . 1) (y . 3) (z . 4) (a . 2) (b . 0) (c . 6))

  ((x . 1) (y . 3) (z . 4) (a . 0) (b . 6) (c . 2))

  ((x . 0) (y . 3) (z . 4) (a . 2) (b . 7) (c . 1))

  ((x . 0) (y . 3) (z . 4) (a . 1) (b . 7) (c . 2)))

Remove impossible options for %can-see:

'(((x . 5) (y . 3) (z . 1) (a . 2) (b . 7) (c . 0))

  ((x . 5) (y . 3) (z . 1) (a . 0) (b . 7) (c . 2))

  ((x . 5) (y . 3) (z . 0) (a . 6) (b . 4) (c . 2))

  ((x . 5) (y . 3) (z . 0) (a . 4) (b . 7) (c . 1))

  ((x . 5) (y . 3) (z . 0) (a . 4) (b . 6) (c . 2))

  ((x . 5) (y . 3) (z . 0) (a . 2) (b . 6) (c . 4))

  ((x . 5) (y . 3) (z . 0) (a . 2) (b . 4) (c . 6))

  ((x . 5) (y . 3) (z . 0) (a . 1) (b . 7) (c . 4))

  ((x . 5) (y . 0) (z . 4) (a . 3) (b . 7) (c . 2))

  ((x . 5) (y . 0) (z . 4) (a . 2) (b . 7) (c . 3))

  ((x . 5) (y . 0) (z . 3) (a . 6) (b . 7) (c . 2))

  ((x . 5) (y . 0) (z . 3) (a . 2) (b . 7) (c . 6))

  ((x . 2) (y . 3) (z . 4) (a . 5) (b . 1) (c . 0))

  ((x . 2) (y . 3) (z . 4) (a . 5) (b . 0) (c . 1))

  ((x . 2) (y . 3) (z . 4) (a . 1) (b . 0) (c . 5))

  ((x . 2) (y . 3) (z . 4) (a . 0) (b . 1) (c . 5))

  ((x . 2) (y . 3) (z . 1) (a . 6) (b . 4) (c . 5))

  ((x . 2) (y . 3) (z . 1) (a . 5) (b . 6) (c . 4))

  ((x . 2) (y . 3) (z . 1) (a . 5) (b . 4) (c . 6))

  ((x . 2) (y . 3) (z . 1) (a . 4) (b . 6) (c . 5))

  ((x . 2) (y . 3) (z . 0) (a . 6) (b . 7) (c . 5))

  ((x . 2) (y . 3) (z . 0) (a . 5) (b . 7) (c . 6))

  ((x . 2) (y . 0) (z . 4) (a . 6) (b . 7) (c . 5))

  ((x . 2) (y . 0) (z . 4) (a . 5) (b . 7) (c . 6))

  ((x . 0) (y . 3) (z . 4) (a . 2) (b . 7) (c . 1))

  ((x . 0) (y . 3) (z . 4) (a . 1) (b . 7) (c . 2)))

Constrain hit counts where possible:

'(((x . 2) (y . 3) (z . 1) (a . 6) (b . 4) (c . 5))

  ((x . 2) (y . 3) (z . 1) (a . 5) (b . 6) (c . 4))

  ((x . 2) (y . 3) (z . 1) (a . 5) (b . 4) (c . 6))

  ((x . 2) (y . 3) (z . 1) (a . 4) (b . 6) (c . 5)))