what must be instead of the ??

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

what must be instead of the ??

Roelof Wobben
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


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

jtuchel
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
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Tim Mackinnon
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
>>
>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Ben Coman
In reply to this post by Roelof Wobben


On Fri, 9 Nov 2018 at 15:25, Roelof Wobben <[hidden email]> wrote:
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 ??

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.
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.

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

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Roelof Wobben
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, 9 Nov 2018 at 15:25, Roelof Wobben <[hidden email]> wrote:
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 ??

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.
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.

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


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Peter Uhnak


On Fri, Nov 9, 2018 at 1:26 PM Roelof Wobben <[hidden email]> wrote:
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


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
Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Roelof Wobben
Op 9-11-2018 om 16:44 schreef Peter Uhnak:


On Fri, Nov 9, 2018 at 1:26 PM Roelof Wobben <[hidden email]> wrote:
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


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

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


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Roelof Wobben
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:
stepChanges := input collect: [ :c |
floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]).
floor
].

stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ].

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

gcotelli
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:
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:
stepChanges := input collect: [ :c |
floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]).
floor
].

stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ].

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Alistair Grant
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

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Peter Uhnak
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:
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:
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:
stepChanges := input collect: [ :c |
floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]).
floor
].

stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ].

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Alistair Grant
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

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

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

Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

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
>
>


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Roelof Wobben
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
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: what must be instead of the ??

Richard O'Keefe
In reply to this post by Roelof Wobben
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:
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:
stepChanges := input collect: [ :c |
floor := floor + (c = '(' ifTrue: [ 1 ] ifFalse: [ -1 ]).
floor
].

stepChanges detectIndex: [ :each | each = -1 ] ifNone: [ 'invalid input yo' ].