this post was submitted on 05 Dec 2024
25 points (100.0% liked)

Advent Of Code

920 readers
1 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 2 years ago
MODERATORS
 

Day 5: Print Queue

Megathread guidelines

  • 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

FAQ

(page 2) 6 comments
sorted by: hot top controversial new old
[–] [email protected] 1 points 1 month ago

Lisp

Part 1 and 2


(defun p1-process-rules (line)
  (mapcar #'parse-integer (uiop:split-string line :separator "|")))

(defun p1-process-pages (line)
  (mapcar #'parse-integer (uiop:split-string line :separator ",")))

(defun middle (pages)
  (nth (floor (length pages) 2) pages))

(defun check-rule-p (rule pages)
  (let ((p1 (position (car rule) pages))
        (p2 (position (cadr rule) pages)))
    (or (not p1) (not p2) (< p1 p2))))

(defun ordered-p (pages rules)
  (loop for r in rules
        unless (check-rule-p r pages)
          return nil
        finally
           (return t)))

(defun run-p1 (rules-file pages-file) 
  (let ((rules (read-file rules-file #'p1-process-rules))
        (pages (read-file pages-file #'p1-process-pages)))
    (loop for p in pages
          when (ordered-p p rules)
            sum (middle p)
          )))

(defun fix-pages (rules pages)
  (sort pages (lambda (p1 p2) (ordered-p (list p1 p2) rules)) ))

(defun run-p2 (rules-file pages-file) 
  (let ((rules (read-file rules-file #'p1-process-rules))
        (pages (read-file pages-file #'p1-process-pages)))
    (loop for p in pages
          unless (ordered-p p rules)
            sum (middle (fix-pages rules p))
          )))

[–] [email protected] 1 points 1 month ago

Uiua

This is the first one that caused me some headache because I didn't read the instructions carefully enough.
I kept trying to create a sorted list for when all available pages were used, which got me stuck in an endless loop.

Another fun part was figuring out to use memberof (∈) instead of find (βŒ•) in the last line of FindNext. So much time spent on debugging other areas of the code

Run with example input here

FindNext ← βŠ™(
  ⊑1⍉,
  βŠƒβ–½(β–½Β¬)⊸∈
  βŠ™βŠ™(⊑0⍉.)
  :βŠ™(⟜(β–½Β¬βˆˆ))
)

# find the order of pages for a given set of rules
FindOrder ← (
  β—΄β™­.
  []
  ⍒(βŠ‚FindNext|β‹…(>1⧻))
  βŠ™β—ŒβŠ‚
)

PartOne ← (
  &rs ∞ &fo "input-5.txt"
  βˆ©Β°β–‘Β°βŠŸβŠœβ–‘Β¬βŒ•"\n\n".
  βŠ™(⊜(β–‘βŠœβ‹•β‰ @,.)β‰ @\n.β†˜1)
  ⊜(βŠœβ‹•β‰ @|.)β‰ @\n.

  βŠ™.
  Β€
  ⊞(β—‘(Β°β–‘:)
    ⟜:βŠ™(Β°βŠŸβ‰)
    =2+∩∈
    β–½
    FindOrder
    βŠΈβ‰Β°β–‘:
    βŠ™β—Œ
  )
  ≑◇(⊑⌊÷2⧻.)β–½β™­
  /+
)

PartTwo ← (
  &rs ∞ &fo "input-5.txt"
  βˆ©Β°β–‘Β°βŠŸβŠœβ–‘Β¬βŒ•"\n\n".
  βŠ™(⊜(β–‘βŠœβ‹•β‰ @,.)β‰ @\n.β†˜1)
  ⊜(βŠœβ‹•β‰ @|.)β‰ @\n.
  βŠ™.
  ⍜€⊞(
    β—‘(Β°β–‘:)
    ⟜:βŠ™(Β°βŠŸβ‰)
    =2+∩∈
    β–½
    FindOrder
    βŠΈβ‰Β°β–‘:
    βŠŸβˆ©β–‘
  )
  βŠ™β—Œ
  βŠƒ(⊑0)(⊑1)⍉
  ≑◇(⊑⌊÷2⧻.)▽¬≑°░
  /+
)

&p "Day 5:"
&pf "Part 1: "
&p PartOne
&pf "Part 2: "
&p PartTwo
[–] [email protected] 1 points 1 month ago

Smalltalk

parsing logic is duplicated between the two, and I probably could use part2's logic for part 1, but yeah

part 1

day5p1: in
	| rules pages i j input |

	input := in lines.
	i := input indexOf: ''.
	rules := ((input copyFrom: 1 to: i-1) collect: [:l | (l splitOn: '|') collect: #asInteger]).
	pages := (input copyFrom: i+1 to: input size) collect: [:l | (l splitOn: ',') collect: #asInteger].
	
	^ pages sum: [ :p |
		(rules allSatisfy: [ :rule |
			i := p indexOf: (rule at: 1).
			j := p indexOf: (rule at: 2).
			(i ~= 0 & (j ~= 0)) ifTrue: [ i < j ] ifFalse: [ true ]
		])
			ifTrue: [p at: ((p size / 2) round: 0) ]
			ifFalse: [0].
	]

part 2

day5p2: in
	| rules pages i pnew input |

	input := in lines.
	i := input indexOf: ''.
	rules := ((input copyFrom: 1 to: i-1) collect: [:l | (l splitOn: '|') collect: #asInteger]).
	pages := (input copyFrom: i+1 to: input size) collect: [:l | (l splitOn: ',') collect: #asInteger].
	
	^ pages sum: [ :p |
		pnew := p sorted: [ :x :y | 
			rules anySatisfy: [ :r | (r at: 1) = x and: [ (r at: 2) = y]]
		].
		pnew ~= p
			ifTrue: [ pnew at: ((pnew size / 2) round: 0) ]
			ifFalse: [0].
	]
[–] [email protected] 1 points 1 month ago* (last edited 1 month ago)

I've got a "smart" solution and a really dumb one. I'll start with the smart one (incomplete but you can infer). I did four different ways to try to get it faster, less memory, etc.

// this is from a nuget package. My Mathy roommate told me this was a topological sort.
// It's also my preferred, since it'd perform better on larger data sets.
return lines
    .AsParallel()
    .Where(line => !IsInOrder(GetSoonestOccurrences(line), aggregateRules))
    .Sum(line => line.StableOrderTopologicallyBy(
            getDependencies: page =>
                aggregateRules.TryGetValue(page, out var mustPreceed) ? mustPreceed.Intersect(line) : Enumerable.Empty<Page>())
        .Middle()
    );

The dumb solution. These comparisons aren't fully transitive. I can't believe it works.

public static SortedSet<Page> Sort3(Page[] line,
    Dictionary<Page, System.Collections.Generic.HashSet<Page>> rules)
{
    // how the hell is this working?
    var sorted = new SortedSet<Page>(new Sort3Comparer(rules));
    foreach (var page in line)
        sorted.Add(page);
    return sorted;
}

public static Page[] OrderBy(Page[] line, Dictionary<Page, System.Collections.Generic.HashSet<Page>> rules)
{
    return line.OrderBy(identity, new Sort3Comparer(rules)).ToArray();
}

sealed class Sort3Comparer : IComparer<Page>
{
    private readonly Dictionary<Page, System.Collections.Generic.HashSet<Page>> _rules;

    public Sort3Comparer(Dictionary<Page, System.Collections.Generic.HashSet<Page>> rules) => _rules = rules;

    public int Compare(Page x, Page y)
    {
        if (_rules.TryGetValue(x, out var xrules))
        {
            if (xrules.Contains(y))
                return -1;
        }

        if (_rules.TryGetValue(y, out var yrules))
        {
            if (yrules.Contains(x))
                return 1;
        }

        return 0;
    }
}
Method Mean Error StdDev Gen0 Gen1 Allocated
Part2_UsingList (literally just Insert) 660.3 us 12.87 us 23.20 us 187.5000 35.1563 1144.86 KB
Part2_TrackLinkedList (wrong now) 1,559.7 us 6.91 us 6.46 us 128.9063 21.4844 795.03 KB
Part2_TopologicalSort 732.3 us 13.97 us 16.09 us 285.1563 61.5234 1718.36 KB
Part2_SortedSet 309.1 us 4.13 us 3.45 us 54.1992 10.2539 328.97 KB
Part2_OrderBy 304.5 us 6.09 us 9.11 us 48.8281 7.8125 301.29 KB
load more comments
view more: β€Ή prev next β€Ί