Advent of code

Advent of Code is upon us, and I’m trying to use Swift to do it! I got the first part done.

https://adventofcode.com/2023/day/1#part2

But I’m struggling with the second part. My code validates the “example” data fine, but it always tells me that for the actual data, my value is too low.

While its kind simple code, it works and reasonably fast. Throw this in an Xcode playground. I’m lost as to what I’m doing wrong, could anyone provide any hints?

let sampleData = """
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
"""

let words:[(String, Int)] = [ ("one", 1 ), ("two", 2), ("three", 3), ("four", 4), ("five", 5), ("six", 6), ("seven", 7), ("eight", 8), ("nine", 9) ]

let lines = sampleData.split( whereSeparator: \.isNewline)
var totalValue:Int = 0
var numbers:[Int]
var leftOvers:String = ""

for cLine in lines {
    leftOvers = ""
    numbers   = []
    
    for character in cLine {
        if let i = Int( String( character ) ) {
            numbers.append( i )
            continue
        }
        
        leftOvers = leftOvers + String( character )
        if leftOvers.count < 3 { continue }
        
        for checkWord in words {
            if !leftOvers.contains( checkWord.0 ) { continue }
            
            numbers.append( checkWord.1 )
            leftOvers = ""
        }
    }
    if let firstNumber = numbers.first, let lastNumber = numbers.last {
        print( "\(( firstNumber * 10 ) + lastNumber)")
        totalValue += ( ( firstNumber * 10 ) + lastNumber )
    }
}
print( "Total: \(totalValue)")

1 Like

I haven’t looked at code for a little while but this got me interested for some reason.

If I’ve got it right the advent of code example is asking you to parse 1000 lines/calibrations?

The last input of the actual data is “trknlxnv43zxlrqjtwonect” which your logic shows as 42 rather than 41 which shows a problem in the logic itself?

Could it be that the o in two is also the o in one so gets passed over if that makes sense?

1 Like

Wouldn’t you be better off going forwards through the string to get the first value and backwards to get the last? Just a thought

This checks out as leftOvers contains nect after the routine is run so one is never picked up

1 Like

why not just process input line by line, filter numbers from string and I think you can directly get the first and the last characters from string with Swift…

That indeed was the problem with my solution.

I tried too many times and was blocked, so I looked up how other people did it. So I’ll forfeit the second point. Not a good start for day 1. Hopefully I can make it up later.

At least this poorly optimized code completed all 1,000 entries in less than a second.

2 Likes

cool - maybe RegEx could have helped as well. Good luck with the rest of the challenges

1 Like

well thats not fun
tried to authenticate using GitHub and got

failed to authenticate. (access_token request returned 429 Too Many Requests)

Signed in using google and its all good
Part 1 worked
Part 2 I had to put down for the time being (work you know)

1 Like

I ran into trouble with part 2 as well.

Here’s a tip (found on Reddit): … Uhh, wasn’t there a way to hide spoilers?

Sam:

let words:[(String, Int)] = [ ("one", 1 ), ("two", 2), ("three", 3), ("four", 4), ("five", 5), ("six", 6), ("seven", 7), ("eight", 8), ("nine", 9) ]

Why do you use tuples in an array here and not simply make a dictionary, i.e.:

let words = ["one":1, "two":2, ...]

(I am trying Swift this time as well, and already learned that a for loop where the upper value changes during the loop won’t get re-evaluated like it happens in most other languages, so that I quickly ran into an out-of-bounds error that took a while to understand.)

Just be aware one example has
Eightwo
And appears to need to be tested as 8 2
So a replace to translate won’t work quite right
Or so it seems

1 Like

No real reason, except to loop through 'em. I coulda done that with a dictionary and the .keys array like you say. I just didn’t think to even consider it.

Oh… I guess you’d have to do it the told fashioned way… Which I’d have to look up how to do it :slight_smile: Like you, I’m still learning Swift and thought it would be a fun challenge to use Swift for it.

Spoiler

Yes, just click the last icon and select ‘Hide Details’ from the dropdown.
image

1 Like

BTW, here’s a few good tips for AoC with Swift, especially for us Swift starters: Advent of Code in Swift. Last month I took part in Advent of… | by Ian Partridge | Medium

It confirms that not all things are great in Swift. Some things are much easier in Xojo, such as loading a text file, as well as many text operations.

1 Like

Concurrency is so stupidly simple in Swift, it really shows how bad that side of Xojo is.

I will confess that I’ve only tried to load plists so far and that was more complicated than it is with Objective-C (one liner). I’d say it was about the same complexity as trying to do it with Xojo.

Where Swift really excels is serialization either to plists or a database.

1 Like

Dealing with Textfiles in Swift is super easy

1 Like

My RegEx skills suck big time, so I just used a simple string search and recorded indices for sorting purposes with my solution for the second part of day 1 using 8th programming language:

{ 1: "1", one: "1",
  2: "2", two: "2",
  3: "3", three: "3",
  4: "4", four: "4",
  5: "5", five: "5",
  6: "6", six: "6",
  7: "7", seven: "7",
  8: "8", eight: "8",
  9: "9", nine: "9" } constant digits

: get-digits
  a:new swap digits m:keys nip 
  ( dup>r
    repeat
      s:search null? !if
        r@ const over extra! 3 roll swap a:push -rot over s:len nip n:1- over n:> !if
          drop rdrop break
        else
          n:1+ r@
        then
      else
        drop rdrop break
      then
    again
   ) a:each! 2drop
   ( extra@ nip swap extra@ nip n:cmp n:neg ) a:sort ;

: lookup-digits
  digits swap [0,-1] a:_@ m:@ nip "" a:join >n ;

: app:main
  0 >r "1.txt" f:slurp ( get-digits lookup-digits n:r+ ) s:eachline r> . cr ;

Thanks for sharing this code, I was able to piece together a magic marker reader.

        let fileHandle = try FileHandle( forReadingFrom: file )

        if let first4Bytes = try fileHandle.read( upToCount: 4 ) {
            let markerID = first4Bytes.withUnsafeBytes { $0.load(as: UInt32.self) }
            switch markerID {
                case FAT_MAGIC, FAT_MAGIC_64, FAT_CIGAM, FAT_CIGAM_64,
                MH_MAGIC, MH_MAGIC_64, MH_CIGAM, MH_CIGAM_64:
                
                isMachOExecutable = true
                
            default:
                break
            }
        }

Here is my 8th solution for the day 2 part 2:

ns?

ns: eval

private

var red
var green
var blue

public

: init
  0 #p:red !
  0 #p:green !
  0 #p:blue ! ;

: red
  #p:red @ n:max #p:red ! ;

: green
  #p:green @ n:max #p:green ! ;

: blue
  #p:blue @ n:max #p:blue ! ;

: power?
  #p:red @ #p:green @ n:* #p:blue @ n:* ;

ns

: app:main
  0 >r "2.txt" f:slurp
  ( ":" s:/ 1 a:_@ ";" s:/ ( "," "" s:replace! ) a:map 
    eval:init ( ns:eval only eval null only ) a:each! drop
    eval:power? n:r+ 
  ) s:eachline r> . cr ;
2 Likes

What language is that?

It’s 8th. I went for easy solution for day 2 part 2 and created words for colors. That allowed me to just split strings and strip away ‘,’ from strings making it a valid 8th syntax. After that eval could simply be used.