[-] janAkali@lemmy.one 4 points 9 hours ago* (last edited 9 hours ago)

maybe Eric and co have begun to realise that family time is more precious than work time

Last year the difficulty was fluctuating from 0 to 100 each day.
This year all problems so far are suspiciously easy. Maybe the second half of the month will be extra hard?

[-] janAkali@lemmy.one 1 points 12 hours ago* (last edited 5 hours ago)

Nim

Overall really simple puzzle, but description is so confusing, that I mostly solved it based on example diagrams.
Edit: much shorter and faster one-pass solution. Runtime: 132 us

type Vec2 = tuple[x,y: int]
func delta(a, b: Vec2): Vec2 = (a.x-b.x, a.y-b.y)
func outOfBounds[T: openarray | string](pos: Vec2, grid: seq[T]): bool =
  pos.x < 0 or pos.y < 0 or pos.x > grid[0].high or pos.y > grid.high

proc solve(input: string): AOCSolution[int, int] =
  var grid = input.splitLines()
  var antennas: Table[char, seq[Vec2]]

  for y, line in grid:
    for x, c in line:
      if c != '.':
        discard antennas.hasKeyOrPut(c, newSeq[Vec2]())
        antennas[c].add (x, y)

  var antinodesP1: HashSet[Vec2]
  var antinodesP2: HashSet[Vec2]

  for _, list in antennas:
    for ind, ant1 in list:
      antinodesP2.incl ant1 # each antenna is antinode
      for ant2 in list.toOpenArray(ind+1, list.high):
        let d = delta(ant1, ant2)
        for dir in [-1, 1]:
          var i = dir
          while true:
            let antinode = (x: ant1.x+d.x*i, y: ant1.y+d.y*i)
            if antinode.outOfBounds(grid): break
            if i in [1, -2]: antinodesP1.incl antinode
            antinodesP2.incl antinode
            i += dir
  result.part1 = antinodesP1.len
  result.part2 = antinodesP2.len


Codeberg repo

[-] janAkali@lemmy.one 4 points 14 hours ago

Where have you seen a human that sits like this? πŸ™ƒ

[-] janAkali@lemmy.one 2 points 1 day ago* (last edited 1 day ago)

Nim

Bruteforce, my beloved.

Wasted too much time on part 2 trying to make combinations iterator (it was very slow). In the end solved both parts with 3^n and toTernary.

Runtime: 1.5s

func digits(n: int): int =
  result = 1; var n = n
  while (n = n div 10; n) > 0: inc result

func concat(a: var int, b: int) =
  a = a * (10 ^ b.digits) + b

func toTernary(n: int, len: int): seq[int] =
  result = newSeq[int](len)
  if n == 0: return
  var n = n
  for i in 0..<len:
    result[i] = n mod 3
    n = n div 3

proc solve(input: string): AOCSolution[int, int] =
  for line in input.splitLines():
    let parts = line.split({':',' '})
    let res = parts[0].parseInt
    var values: seq[int]
    for i in 2..parts.high:
      values.add parts[i].parseInt

    let opsCount = values.len - 1
    var solvable = (p1: false, p2: false)
    for s in 0 ..< 3^opsCount:
      var sum = values[0]
      let ternary = s.toTernary(opsCount)
      for i, c in ternary:
        case c
        of 0: sum *= values[i+1]
        of 1: sum += values[i+1]
        of 2: sum.concat values[i+1]
        else: raiseAssert"!!"
      if sum == res:
        if ternary.count(2) == 0:
          solvable.p1 = true
        solvable.p2 = true
        if solvable == (true, true): break
    if solvable.p1: result.part1 += res
    if solvable.p2: result.part2 += res

Codeberg repo

[-] janAkali@lemmy.one 2 points 2 days ago* (last edited 2 days ago)

Nim

Not the prettiest code, but it runs in 3 seconds. For part 2 I just place an obstacle at every position guard visited in part 1.

Edit: made step procedure more readable.

type
  Vec2 = tuple[x,y: int]
  Dir = enum
    Up, Right, Down, Left
  Guard = object
    pos: Vec2
    dir: Dir

proc step(guard: var Guard, map: seq[string]): bool =
  let next: Vec2 =
    case guard.dir
    of Up: (guard.pos.x, guard.pos.y-1)
    of Right: (guard.pos.x+1, guard.pos.y)
    of Down: (guard.pos.x, guard.pos.y+1)
    of Left: (guard.pos.x-1, guard.pos.y)

  if next.y < 0 or next.x < 0 or next.y > map.high or next.x > map[0].high:
    return false
  elif map[next.y][next.x] == '#':
    guard.dir = Dir((guard.dir.ord + 1) mod 4)
  else:
    guard.pos = next
  true

proc solve(input: string): AOCSolution[int, int] =
  var map = input.splitLines()
  var guardStart: Vec2
  block findGuard:
    for y, line in map:
      for x, c in line:
        if c == '^':
          guardStart = (x, y)
          map[y][x] = '.'
          break findGuard

  var visited: HashSet[Vec2]
  block p1:
    var guard = Guard(pos: guardStart, dir: Up)
    while true:
      visited.incl guard.pos
      if not guard.step(map): break
    result.part1 = visited.len

  block p2:
    for (x, y) in visited - [guardStart].toHashSet:
      var loopCond: HashSet[Guard]
      var guard = Guard(pos: guardStart, dir: Up)
      var map = map
      map[y][x] = '#'

      while true:
        loopCond.incl guard
        if not guard.step(map): break
        if guard in loopCond:
          inc result.part2
          break

Codeberg repo

[-] janAkali@lemmy.one 2 points 2 days ago

Good old bubble sort

[-] janAkali@lemmy.one 0 points 2 days ago

You can put egregious amount of cheese on anything and it would taste atleast half as good as pizza.

[-] janAkali@lemmy.one 6 points 3 days ago* (last edited 3 days ago)

Nim

Solution: sort numbers using custom rules and compare if sorted == original. Part 2 is trivial.
Runtime for both parts: 1.05 ms

proc parseRules(input: string): Table[int, seq[int]] =
  for line in input.splitLines():
    let pair = line.split('|')
    let (a, b) = (pair[0].parseInt, pair[1].parseInt)
    discard result.hasKeyOrPut(a, newSeq[int]())
    result[a].add b

proc solve(input: string): AOCSolution[int, int] =
  let chunks = input.split("\n\n")
  let later = parseRules(chunks[0])
  for line in chunks[1].splitLines():
    let numbers = line.split(',').map(parseInt)
    let sorted = numbers.sorted(cmp =
      proc(a,b: int): int =
        if a in later and b in later[a]: -1
        elif b in later and a in later[b]: 1
        else: 0
    )
    if numbers == sorted:
      result.part1 += numbers[numbers.len div 2]
    else:
      result.part2 += sorted[sorted.len div 2]

Codeberg repo

[-] janAkali@lemmy.one 4 points 4 days ago* (last edited 4 days ago)

Nim

Could be done more elegantly, but I haven’t bothered yet.

proc solve(input: string): AOCSolution[int, int] =
  var lines = input.splitLines()

  block p1:
    # horiz
    for line in lines:
      for i in 0..line.high-3:
        if line[i..i+3] in ["XMAS", "SAMX"]:
          inc result.part1

    for y in 0..lines.high-3:
      #vert
      for x in 0..lines[0].high:
        let word = collect(for y in y..y+3: lines[y][x])
        if word in [@"XMAS", @"SAMX"]:
          inc result.part1

      #diag \
      for x in 0..lines[0].high-3:
        let word = collect(for d in 0..3: lines[y+d][x+d])
        if word in [@"XMAS", @"SAMX"]:
          inc result.part1

      #diag /
      for x in 3..lines[0].high:
        let word = collect(for d in 0..3: lines[y+d][x-d])
        if word in [@"XMAS", @"SAMX"]:
          inc result.part1

  block p2:
    for y in 0..lines.high-2:
      for x in 0..lines[0].high-2:
        let diagNW = collect(for d in 0..2: lines[y+d][x+d])
        let diagNE = collect(for d in 0..2: lines[y+d][x+2-d])
        if diagNW in [@"MAS", @"SAM"] and diagNE in [@"MAS", @"SAM"]:
          inc result.part2

Codeberg repo

[-] janAkali@lemmy.one 5 points 5 days ago* (last edited 5 days ago)

Nim

From a first glance it was obviously a regex problem.
I'm using tinyre here instead of stdlib re library just because I'm more familiar with it.

import pkg/tinyre

proc solve(input: string): AOCSolution[int, int] =
  var allow = true
  for match in input.match(reG"mul\(\d+,\d+\)|do\(\)|don't\(\)"):
    if match == "do()": allow = true
    elif match == "don't()": allow = false
    else:
      let pair = match[4..^2].split(',')
      let mult = pair[0].parseInt * pair[1].parseInt
      result.part1 += mult
      if allow: result.part2 += mult

Codeberg repo

[-] janAkali@lemmy.one 2 points 5 days ago* (last edited 5 days ago)

Cool to see another solution in Nim here =)

(0..<record.len).anyIt(record.dup(delete(it)).validate)

That's smart. I haven't thought of using iterators to loop over indexes (except in a for loop).

I got stuck on part 2 trying to check everything inside a single loop, which kept getting more ugly.

Yeah I've thought of simple ways to do this and found none. And looking at the input - it's too easy to bruteforce, especially in compiled lang like Nim.

[-] janAkali@lemmy.one 12 points 6 days ago

Hey, why isn’t China more green? I’d think the CCP hates western spyware OSes.

10
submitted 1 week ago* (last edited 1 week ago) by janAkali@lemmy.one to c/nim@programming.dev

Reposted from forum.

I couldn't find an existing compilation of Nim practice websites, so
I thought it would be helpful to create one. Here's what I've found so far:

Sites with Native Nim Support:

  • Exercism - Low difficulty, excellent support, best experience, uses latest Nim compiler
  • Code Golf - Can be used as general programming challenge website, supports latest Nim compiler
  • Kattis - All ranges of difficulty, 5000+ problems, uses Nim v2.0.0
  • CodeWars - Easy and Medium difficulty, most katas use outdated Nim v1.6 compiler, some even older version
  • Sphere Online Judge - Uses Nim v0.19.4

Sites Supporting JavaScript (Compatible with Nim's JS Backend):

  • LeetCode - Add {.exportc.} pragma to your function and compile with -b:js backend
  • Potentially all other programming challenges websites that support js or nodejs, but I've only tested leetcode.

Language-Agnostic Websites (Text/Output Based):

  • Advent of Code - good quality Christmas-themed puzzles, runs in December (see y'all in a week!)
  • Everybody Codes - similar to Advent of Code, but starts one month early
  • Project Euler - mathematical/programming problems, difficulty spike past first 100 problems
  • The Weekly Challenge - submissions are not checked

Please share any other resources you know!

19
submitted 1 month ago by janAkali@lemmy.one to c/gaming@beehaw.org
47
submitted 8 months ago by janAkali@lemmy.one to c/linux@lemmy.ml

Probably a long way from being daily-driven, but I really love the idea.
Interview with creator: https://www.youtube.com/watch?v=uMzbVBpjFiM

view more: next β€Ί

janAkali

joined 2 years ago