Hello,
I try to solve a adventofcode challenge where I must find out when santa is first at the basement. the floor is there -1. So I thought I use a while loop like this : santaFloorOnBasement "calculates which step take Santa to the basement" | index| index := 1. ??? when: (floor >=0 ) do: [ floor := (input at: index = '(' ) ifTrue: [ floor + 1 ] ifFalse: [ floor - 1 ]. index := index + 1 ]. but I cannot find out what must be instead of the ?? index is the index of the string which has to start with a 1. floor and input are both instance variables. floor contains the current floor and input the input of the challenge. Can someone help me figure this out so the next time I can do this on my own. Roelof |
So I guess that floor > 0 is your condition, right? In Smalltalk, the idea is that you evaluate the condition and ask the result of it (usually true or false) to do something.
Right so far? That would mean the receiver of your wanted message is either the result of the evaluation or or a Block which will be evaluated in a construct like ifTrue: or something like whileTrue: HTH Joachim > Am 09.11.2018 um 08:24 schrieb Roelof Wobben <[hidden email]>: > > Hello, > > I try to solve a adventofcode challenge where I must find out when santa is first at the basement. the floor is there -1. > So I thought I use a while loop like this : > > santaFloorOnBasement > "calculates which step take Santa to the basement" > | index| > index := 1. > ??? when: (floor >=0 ) do: > [ floor := (input at: index = '(' ) > ifTrue: [ floor + 1 ] > ifFalse: [ floor - 1 ]. > index := index + 1 ]. > > but I cannot find out what must be instead of the ?? > > index is the index of the string which has to start with a 1. > floor and input are both instance variables. floor contains the current floor and input the input of the challenge. > > Can someone help me figure this out so the next time I can do this on my own. > > Roelof > > > |
To add to what Joachim has said, and to help you help yourself, look at what methods are implemented in BlockClosure and Boolean and see how things work (the code is there for you to understand it quite easily - there is little magic going on). You can find all kinds of interesting and helpful things and can even implement your own if you ever want to.
Tim Sent from my iPhone > On 9 Nov 2018, at 16:02, Joachim Tuchel <[hidden email]> wrote: > > So I guess that floor > 0 is your condition, right? In Smalltalk, the idea is that you evaluate the condition and ask the result of it (usually true or false) to do something. > > Right so far? That would mean the receiver of your wanted message is either the result of the evaluation or or a Block which will be evaluated in a construct like ifTrue: or something like whileTrue: > > HTH > > Joachim > > > >> Am 09.11.2018 um 08:24 schrieb Roelof Wobben <[hidden email]>: >> >> Hello, >> >> I try to solve a adventofcode challenge where I must find out when santa is first at the basement. the floor is there -1. >> So I thought I use a while loop like this : >> >> santaFloorOnBasement >> "calculates which step take Santa to the basement" >> | index| >> index := 1. >> ??? when: (floor >=0 ) do: >> [ floor := (input at: index = '(' ) >> ifTrue: [ floor + 1 ] >> ifFalse: [ floor - 1 ]. >> index := index + 1 ]. >> >> but I cannot find out what must be instead of the ?? >> >> index is the index of the string which has to start with a 1. >> floor and input are both instance variables. floor contains the current floor and input the input of the challenge. >> >> Can someone help me figure this out so the next time I can do this on my own. >> >> Roelof >> >> >> > > |
In reply to this post by Roelof
On Fri, 9 Nov 2018 at 15:25, Roelof Wobben <[hidden email]> wrote: Hello, I've never used #when:do: so I can't comment on that. I'd be using #whileTrue: which looks like this... [ condition block ] whileTrue: [ action block ] <<< ??? when: (floor >=0 ) do: >>> [floor>=0] whileTrue: For further examples review the "senders" of #whileTrue: i.e. highlight then press <CTRL-N> on MS Windows index is the index of the string which has to start with a 1. btw you have a problem here... floor := (input at: index = '(' ) Its not doing what you think and you'll get "Error: only integers should be used as indices" Consider you that two messages are being sent: * the keyword message... #at: * the binary message.... #= Homework :)... what is the third type of message and the evaluation priority of all three. Homework 2... Review the "implementors" of message #= <CTRL-M> on MS Windows cheers -ben P.S. As it current stands, you'll get a "SubscriptOutOfBounds" error if the input ends before Santa gets to the basement. An exercise, fix that using the existing loop. Then consider using an iterator... input do: [ :bracket | (bracket = $( ) ifTrue:
[ floor := floor + 1 ] . (bracket = $( ) ifTrue:
[ floor := floor + 1 ] ]. and maybe something else for you to experiment with... movement := Dictionary new. movement at: $( put: 1. movement at: $) put: -1. input do: [ :char | floor := floor + (movement at: char ifAbsent: [0]) ]. cheers -ben |
Thanks all.
This code seems to do the job santaFloorOnBasement "calculates which step take Santa to the basement" | index| index := 1. [floor ~= -1 ] whileTrue: [ floor := ((input at: index) = '(' ) ifTrue: [ floor + 1 ] ifFalse: [ floor - 1 ]. index := index + 1 ]. ^ index -1 Roelof Op 9-11-2018 om 09:51 schreef Ben Coman:
|
On Fri, Nov 9, 2018 at 1:26 PM Roelof Wobben <[hidden email]> wrote:
You can also think of it from the perspective of data processing and not instruction coding (and mangling of indexes). stepChanges := input collect: [ :c | floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). floor ]. stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ]. Peter |
Op 9-11-2018 om 16:44 schreef Peter
Uhnak:
oke, I see how it works, first you calculate all the floors Santa is visiting and then you look for the first -1. I have thought of something but I found it wierd that you do steps when you have already the answer. but how do I find now the answer do I have to do something like puzzle1 stepChanges detectIndex ? Roelof |
hmm.
When I try this on P7 |input stepChanges floor| input := '((('. floor := 0. stepChanges := input collect: [ :c | floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). floor ]. stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ]. then I see this error message : Improper store to indexable object. Roelof Op 9-11-2018 om 17:39 schreef Roelof Wobben:
|
It's bug in the collect: implementation used in String. I've opened https://pharo.fogbugz.com/f/cases/22652/collect-over-Strings-is-broken On Fri, Nov 9, 2018 at 2:17 PM Roelof Wobben <[hidden email]> wrote:
|
On Fri, 9 Nov 2018 at 18:38, Gabriel Cotelli <[hidden email]> wrote:
> > It's bug in the collect: implementation used in String. I've opened https://pharo.fogbugz.com/f/cases/22652/collect-over-Strings-is-broken Strings store characters, not integers, so change your example to: 'aa' collect: [ :a | $1 ] and you'll see that (I think) it is working as expected. You could do: 'aa' collect: [ :a | 1 ] as: Array. Roelof, revisit your example, taking the above in to account :-) HTH, Alistair |
In reply to this post by gcotelli
but how do I find now the answer do I have to do something like puzzle1 stepChanges detectIndex ? How do you mean? It would be the same santaFloorOnBasement "calculates which step take Santa to the basement" stepChanges := input collect: [ :c | floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). floor ]. stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ]. then I see this error message : Improper store to indexable object. Because earlier you were comparing strings and not characters, I assumed your input was an array of strings like #('(' '(' '('). but you can fix that by changing `input collect:` -> `input asArray collect:` and `c = '('` -> `c = $(`. I have thought of something but I found it wierd that you do steps when you have already the answer. That is indeed true, personally I would decide based on how often the method is called and how large the input is. Because this cumulative change makes it much easier to debug any issues... and usually I prefer debuggability over performance (unless it is an actual bottleneck). Peter On Fri, Nov 9, 2018 at 6:38 PM Gabriel Cotelli <[hidden email]> wrote:
|
Hi Peter,
On Fri, 9 Nov 2018 at 18:51, Peter Uhnak <[hidden email]> wrote: >> >> but how do I find now the answer do I have to do something like puzzle1 stepChanges detectIndex ? > > > How do you mean? It would be the same > > santaFloorOnBasement > "calculates which step take Santa to the basement" > > stepChanges := input collect: [ :c | > floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). > floor > ]. > > stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ]. > >> then I see this error message : Improper store to indexable object. > > > Because earlier you were comparing strings and not characters, I assumed your input was an array of strings like #('(' '(' '('). but you can fix that by changing `input collect:` -> `input asArray collect:` and `c = '('` -> `c = $(`. Using '(' instead of $( is indeed an error, but it isn't the cause of the Improper store error. Roelof, I really suggest you trigger this error again, start the debugger and then take a look in the call stack (I'm assuming you're familiar with at least one other programming language, so should be able to figure out the debugger). Cheers, Alistair |
Hi Peter,
On Fri, 9 Nov 2018 at 19:00, Alistair Grant <[hidden email]> wrote: > > Hi Peter, > > On Fri, 9 Nov 2018 at 18:51, Peter Uhnak <[hidden email]> wrote: > >> > >> but how do I find now the answer do I have to do something like puzzle1 stepChanges detectIndex ? > > > > > > How do you mean? It would be the same > > > > santaFloorOnBasement > > "calculates which step take Santa to the basement" > > > > stepChanges := input collect: [ :c | > > floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). > > floor > > ]. > > > > stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ]. > > > >> then I see this error message : Improper store to indexable object. > > > > > > Because earlier you were comparing strings and not characters, I assumed your input was an array of strings like #('(' '(' '('). but you can fix that by changing `input collect:` -> `input asArray collect:` and `c = '('` -> `c = $(`. > > Using '(' instead of $( is indeed an error, but it isn't the cause of > the Improper store error. I was too quick to respond here, I didn't look at the #asArray. Sorry! But still suggest Roelof looks at the debugger... > Roelof, I really suggest you trigger this error again, start the > debugger and then take a look in the call stack (I'm assuming you're > familiar with at least one other programming language, so should be > able to figure out the debugger). Cheers, Alistair |
hmm, got a idea
I could use this part : |input floor stepChanges| input := '))((((('. floor := 0. stepChanges := input asArray collect: [ :c | floor := floor + (c = $( ifTrue: [ 1 ] ifFalse: [ -1 ]). ]. two times if the outcome would be a collection. The challenge is 2 parts. 1) find out where santa stops. that would be the last number in the collection.. 2) find out when santa enters the basement. That could be the function that is mentioned here. Time to experiment with this idea. Roelof Op 9-11-2018 om 19:13 schreef Alistair Grant: > Hi Peter, > > On Fri, 9 Nov 2018 at 19:00, Alistair Grant <[hidden email]> wrote: >> Hi Peter, >> >> On Fri, 9 Nov 2018 at 18:51, Peter Uhnak <[hidden email]> wrote: >>>> but how do I find now the answer do I have to do something like puzzle1 stepChanges detectIndex ? >>> >>> How do you mean? It would be the same >>> >>> santaFloorOnBasement >>> "calculates which step take Santa to the basement" >>> >>> stepChanges := input collect: [ :c | >>> floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). >>> floor >>> ]. >>> >>> stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ]. >>> >>>> then I see this error message : Improper store to indexable object. >>> >>> Because earlier you were comparing strings and not characters, I assumed your input was an array of strings like #('(' '(' '('). but you can fix that by changing `input collect:` -> `input asArray collect:` and `c = '('` -> `c = $(`. >> Using '(' instead of $( is indeed an error, but it isn't the cause of >> the Improper store error. > I was too quick to respond here, I didn't look at the #asArray. Sorry! > > But still suggest Roelof looks at the debugger... > >> Roelof, I really suggest you trigger this error again, start the >> debugger and then take a look in the call stack (I'm assuming you're >> familiar with at least one other programming language, so should be >> able to figure out the debugger). > Cheers, > Alistair > > |
Given up for today
I have this : calculateFloors | stepChanges floor| floor := 0. stepChanges := input asArray collect: [ :c | floor := floor+ (c = $( ifTrue: [ 1 ] ifFalse: [ -1 ]). ]. floors addFloor: floor. but now I see this error message : temp values not written or read. floors and input are instance variables where input is the input the user wants to use and floors is a Collection new. Roelof Op 9-11-2018 om 20:07 schreef Roelof Wobben: > hmm, got a idea > > I could use this part : > > |input floor stepChanges| > input := '))((((('. > floor := 0. > stepChanges := input asArray collect: [ :c | > floor := floor + (c = $( ifTrue: [ 1 ] ifFalse: [ -1 ]). > ]. > > > two times if the outcome would be a collection. > The challenge is 2 parts. > > 1) find out where santa stops. that would be the last number in the > collection.. > 2) find out when santa enters the basement. That could be the function > that is mentioned here. > > Time to experiment with this idea. > > Roelof > > > Op 9-11-2018 om 19:13 schreef Alistair Grant: >> Hi Peter, >> >> On Fri, 9 Nov 2018 at 19:00, Alistair Grant <[hidden email]> >> wrote: >>> Hi Peter, >>> >>> On Fri, 9 Nov 2018 at 18:51, Peter Uhnak <[hidden email]> wrote: >>>>> but how do I find now the answer do I have to do something like >>>>> puzzle1 stepChanges detectIndex ? >>>> >>>> How do you mean? It would be the same >>>> >>>> santaFloorOnBasement >>>> "calculates which step take Santa to the basement" >>>> >>>> stepChanges := input collect: [ :c | >>>> floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]). >>>> floor >>>> ]. >>>> >>>> stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ >>>> 'invalid input yo' ]. >>>> >>>>> then I see this error message : Improper store to indexable object. >>>> >>>> Because earlier you were comparing strings and not characters, I >>>> assumed your input was an array of strings like #('(' '(' '('). but >>>> you can fix that by changing `input collect:` -> `input asArray >>>> collect:` and `c = '('` -> `c = $(`. >>> Using '(' instead of $( is indeed an error, but it isn't the cause of >>> the Improper store error. >> I was too quick to respond here, I didn't look at the #asArray. Sorry! >> >> But still suggest Roelof looks at the debugger... >> >>> Roelof, I really suggest you trigger this error again, start the >>> debugger and then take a look in the call stack (I'm assuming you're >>> familiar with at least one other programming language, so should be >>> able to figure out the debugger). >> Cheers, >> Alistair >> >> > > > |
In reply to this post by Roelof
We are talking to a beginner here. One of the important things for a beginner to understand is the idea of hiding stuff and thinking in terms of asking objects to do things for you. For example, in Java you historically did final int n = aString.length(); for (int i = 0; i < n; i++) { final char c = aString.charAt(i); ... } Here all the loop control is *outside* the string, and if you wanted to use some other data structure you would have to change the code. But in Smalltalk, you ask the *object* to manage the iteration. For collections in general, we have aCollection do: [:anElement | ... ] For sequences we also have aSequence withIndexDo: [:anElement :itsIndex | ...] where the sequence need not be a stored sequence and need not be efficiently indexable. (And indeed, in Java these days, Strings *aren't* efficiently indexable, thanks to using UTF-16 internally.) Using enumeration methods (a) makes your code easier to read (b) makes your code easier to write (as there is lots of fiddly detail you don't write at all, it's there once and for all in the class) (c) makes your code more adaptable (the object needs to support #withIndexDo: and that is *all* you demand of it). indexWhereBasementFirstReached: input "The input is a sequence in which the character ( means to go up a floor and the character ) means to go down a floor. Answer the index of the character where the floor below the initial floor is first reached. If that floor is not reached, e.g., if the input is empty, answer 0. This is the same convention as #indexOf:." |floor| floor := 0. input withIndexDo: [:char :index | char = $( ifTrue: [floor := floor + 1]. char = $) ifTrue: [floor := floor - 1]. floor = -1 ifTrue: [^index]]. ^0 For example, we could add the #withIndexDo: method to Stream, which already has #do: withIndexDo: elementAndIndexBlock "Iterate over the 'future values' remaining in this stream, passing each in turn to the block argument, together with an index starting at 1 for the first value passed to the block." |index| index := 0. self do: [:each | elementAndIndexBlock value: each value: (index := index + 1)]. Now the #indexWhereBasementFirstReached: method will work on input streams as well as strings, so it could, for example, handle a terabyte long sequence held in a file. On Sat, 10 Nov 2018 at 06:17, Roelof Wobben <[hidden email]> wrote:
|
Free forum by Nabble | Edit this page |