Advent of Code 2019

37 views
Skip to first unread message

Abraham Palmer

unread,
Dec 4, 2019, 6:59:25 AM12/4/19
to amber-lang
I have a longer-term project of using Amber as the front-end of secure and distributed applications built on HoloChain. I'm new to SmallTalk though and have been enjoying learning in Amber via the coding challenges at Advent of Code.  There are two challenges each day and I think they normally build on eachother so you also get practice modifying/extending an existing solution. I keep running into the things I don't know how to do, but often just a search in Helios on something like "floor" comes up with what I need. I was hoping others might want to play along and share problems/solutions. For instance I haven't been able to get the load of the data input from a URL working yet (loadData). Here's some working code from the Day 1 challenge to give you an idea. 

TestCase subclass: #AOCTest
   slots: {}
   package: 'Examples'!

!AOCTest methodsFor: 'tests'!

testFuel
   "Run the tests in the example"

    self assert: (Module new: 12) fuel = 2.
   self assert: (Module new: 14) fuel = 2.
   self assert: (Module new: 1969) fuel = 966.
   self assert: (Module new: 100756) fuel = 50346.
! !

Object subclass: #Day
   slots: {#star1. #star2}
   package: 'Examples'!

!Day methodsFor: 'as yet unclassified'!

loadData: aURL
   "Helper function to load data from URL to an array"
   
   | xhr |
   
   xhr := Platform newXhr
       open: 'GET' url: aURL ;
       onload: [ :data | ^data ];
       onerror: [ :error | Transcript show: 'Request Failed:', error. ^nil];
       send.
!

star1
   "The Fuel Counter-Upper needs to know the total fuel requirement. To find it,
    individually calculate the fuel needed for the mass of each module (your puzzle input),
    then add together all the fuel values.

    What is the sum of the fuel requirements for all of the modules on your spacecraft?"

    | text total |
   text := '147077
148686
71851
98056
65024
87254
146003
128542
136657
91885
91904
78806
58210
67520
118393
68344
69593
135370
111892
84153
105683
76166
112780
145179
83811
61481
118277
59732
72222
64606
55645
82168
97590
122479
120365
103057
76225
148099
100610
75592
148678
132756
55335
77094
73992
95097
92382
78885
93657
121709
114261
90565
110043
145497
92066
109833
76107
143941
67084
139407
56730
131457
110026
85632
74239
116964
129806
75030
76317
99523
78069
75685
81279
58287
148135
89313
139141
136066
94046
50430
55242
123494
68410
83716
122608
79343
88826
95968
98603
104895
128814
120473
97504
60990
98132
58895
92987
136301
131747
137498'.
   total := 0.
   text lines do: [:m | total := total + ((Module new: (m asNumber)) fuel)].
   ^total
! !

Object subclass: #Intcode
   slots: {#memory. #step}
   package: 'Examples'!

Object subclass: #Module
   slots: {#mass. #cumfuel}
   package: 'Examples'!

!Module methodsFor: 'as yet unclassified'!

fuel
   "Fuel is now pre-calculated when Module created."

    ^cumfuel
!

fuelMass: aMass
   "Recursively add in additional mass needed to account for the fuel.
   Fuel required to launch a given module is based on its mass.
    Specifically, to find the fuel required for a module, take its mass,
    divide by three, round down, and subtract 2."
   | thefuel |

    thefuel := (aMass / 3) floor - 2.
   thefuel > 0
       ifTrue: [ cumfuel := cumfuel + thefuel. self fuelMass: thefuel ]
       ifFalse: [ ^cumfuel ].
!

mass: aMass
   "Set the mass"

    mass := aMass.
   cumfuel := 0.
   self fuelMass: aMass.
! !


Herby Vojčík

unread,
Dec 4, 2019, 7:53:13 AM12/4/19
to amber...@googlegroups.com, Abraham Palmer
Hi!

Smalltalk is written with lowercase t, as one word. ;-)

IIRC you can get `(foo / bar) floor` as `foo // bar`.

Instead of parsing text and doing `stringWithNumberLines lines do:`, why
not just use literal array of numbers like `#(4 5 6 ...) do: ...` (you
can have newlines as separators inside literal array as well, so you can
reuse format of your method, just don't use string but more natural
container)? And since you are computing a total, the correct
Smalltalkish way is to use #inject:into: instead of #do: (how exactly is
left as an exercise for the reader :-) ).

Instead of `Platform newXhr`, try to use `Platform fetch:` family of
URLs, they build on more modern fetch() browser API.

The problem of your loadData is that getting data is asynchronous; the
method actually ends immediately, returning self as the default and
initiates the loading process, but result is only present in the future.
One way is to use callbacks, actually you could write

loadData: aUrl thenDo: aBlock
Platform newXhr
open: 'GET' url: aUrl ;
onload: aBlock;
onerror: [ :error | Transcript show:'Request Failed:', error ];
send

and in your code you should pass the block which uses the data once they
come in. As mentioned, using fetch API is probably better; fetch API
returns a Promise of the result so it could be something like (guessing,
not remembering actual fetch API details):

loadData: aUrl thenDo: aBlock
(Platform fetch: aUrl)
then: aBlock
catch: [ :error | Transcript show:'Request Failed:', error ]

and then call `foo loadData: myUrl thenDo: [ :data | ... ]`, or

loadData: aUrl
^ Platform fetch: aUrl "maybe with options"

and then treat a Promise directly, as in

(foo loadData: myUrl) then: [ :data | ... ]

(nitpick: please use space after keyword: messages, it's how it is
common in Smalltalk, unlike in ObjectiveC which took the syntax and idea
of objects from Smalltalk but where they don't put the space and keyword:)

Have fun,

Herby

On 4. 12. 2019 12:59, Abraham Palmer wrote:
> I have a longer-term project of using Amber as the front-end of secure
> and distributed applications built on HoloChain
> <https://holochain.org/>. I'm new to SmallTalk though and have been
> enjoying learning in Amber via the coding challenges at Advent of Code
> <https://adventofcode.com/2019>.  There are two challenges each day and
> I think they normally build on eachother so you also get practice
> modifying/extending an existing solution. I keep running into the things
> I don't know how to do, but often just a search in Helios on something
> like "floor" comes up with what I need. I was hoping others might want
> to play along and share problems/solutions. For instance I haven't been
> able to get the load of the data input from a URL working yet
> (loadData). Here's some working code from the Day 1 challenge to give
> you an idea.
>
> |
> TestCasesubclass:#AOCTest
>    slots: {}
>    package: 'Examples'!
>
> !AOCTestmethodsFor:'tests'!
>
> testFuel
> "Run the tests in the example"
>
> selfassert:(Modulenew:12)fuel =2.
> selfassert:(Modulenew:14)fuel =2.
> selfassert:(Modulenew:1969)fuel =966.
> selfassert:(Modulenew:100756)fuel =50346.
> !!
>
> Objectsubclass:#Day
>    slots: {#star1. #star2}
>    package: 'Examples'!
>
> !DaymethodsFor:'as yet unclassified'!
> Objectsubclass:#Intcode
>    slots: {#memory. #step}
>    package: 'Examples'!
>
> Objectsubclass:#Module
>    slots: {#mass. #cumfuel}
>    package: 'Examples'!
>
> !ModulemethodsFor:'as yet unclassified'!
>
> fuel
> "Fuel is now pre-calculated when Module created."
>
> ^cumfuel
> !
>
> fuelMass:aMass
> "Recursively add in additional mass needed to account for the fuel.
>    Fuel required to launch a given module is based on its mass.
>     Specifically, to find the fuel required for a module, take its mass,
>     divide by three, round down, and subtract 2."
> |thefuel|
>
>     thefuel :=(aMass /3)floor -2.
>    thefuel >0
> ifTrue:[cumfuel :=cumfuel +thefuel.selffuelMass:thefuel ]
> ifFalse:[^cumfuel ].
> !
>
> mass:aMass
> "Set the mass"
>
>     mass :=aMass.
>    cumfuel :=0.
> selffuelMass:aMass.
> !!
> |
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "amber-lang" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to amber-lang+...@googlegroups.com
> <mailto:amber-lang+...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/amber-lang/36d89bf9-0a94-47c5-9495-054bc5069f1a%40googlegroups.com
> <https://groups.google.com/d/msgid/amber-lang/36d89bf9-0a94-47c5-9495-054bc5069f1a%40googlegroups.com?utm_medium=email&utm_source=footer>.


Abraham Palmer

unread,
Dec 4, 2019, 11:00:48 AM12/4/19
to Herby Vojčík, amber...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages