Quest 8: The Art of Connection

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

Link to participate: https://everybody.codes/

  • janAkali@lemmy.sdf.org
    link
    fedilink
    arrow-up
    2
    ·
    8 days ago

    Nim

    Part 2 - I just really didn’t want to think that day. So when puzzle asked me to check if lines intersect - I wrote the intersection checking solution with 2D points.

    Part 3 is geometry + bruteforce.

    proc solve_part1*(input: string): Solution =
      let pins = input.split(',').mapIt(parseInt(it))
      for i in 0 ..< pins.high:
        let d = abs(pins[i] - pins[i+1])
        if d == 16: inc result.intVal
    
    proc ccw(A,B,C: Vec2): bool = (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)
    proc isIntersection(A,B,C,D: Vec2): bool = ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
    
    proc solve_part2*(input: string): Solution =
      const two_pi = PI * 2
      const pin_count = 256
    
      var pins: array[pin_count, Vec2]
      for i in 0 ..< pin_count:
        let angle = two_pi * (i / pin_count)
        let point: Vec2 = (cos(angle), sin(angle))
        pins[i] = point
    
      let inst = input.split(',').mapIt(parseInt(it))
      var lines: seq[(Vec2, Vec2)]
    
      for i in 0 ..< inst.high:
        let A = pins[inst[i]-1]
        let B = pins[inst[i+1]-1]
    
        for (C, D) in lines:
          if isIntersection(A,B,C,D):
            inc result.intVal
        lines.add shortenSegment(A, B, 0.0001)
    
    proc solve_part3*(input: string): Solution =
      const two_pi = PI * 2
      const pin_count = 256
    
      var pins: array[pin_count, Vec2]
      for i in 0 ..< pin_count:
        let angle = two_pi * (i / pin_count)
        let point: Vec2 = (cos(angle), sin(angle))
        pins[i] = point
    
      let inst = input.split(',').mapIt(parseInt(it))
      var lines: seq[(Vec2, Vec2)]
    
      for i in 0 ..< inst.high:
        let A = pins[inst[i]-1]
        let B = pins[inst[i+1]-1]
        lines.add shortenSegment(A, B, 0.0001)
    
      var bestSum = 0
      for i in 0 ..< pin_count:
        for j in i+1 ..< pin_count:
          let A = pins[i]
          let B = pins[j]
          var sum = 0
          for (C, D) in lines:
            if isIntersection(A,B,C,D): inc sum
          if sum > bestSum: bestSum = sum
      result := bestSum
    

    Full solution at Codeberg: solution.nim