Error while trying to write numbers in words

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

Error while trying to write numbers in words

ZuLuuuuuu
Hello,

I am trying to write a method called "inWords" for Number class to write a
number in words. For example:

15 inWords

should output:

fifteen

I wrote a code, it works for every 2 digit number except 19, for which it
outputs "tennine". I guess there is a logic error in algorithm but I cannot find
it. Anyone has an idea? Here is the code:

Number extend [
    inWords [
        | clone part_1 part_2 part_3 |
       
        part_1 := ''.
        part_2 := ''.
        part_3 := ''.

        clone := self copy.
       
        ((clone \\ 100) = 0) ifTrue: [
            part_1 := ''.
            part_2 := ''.
        ].
        ((clone \\ 100) < 20 and: [(clone \\ 100) > 10]) ifTrue: [
            ((clone \\ 100) = 11) ifTrue: [
                part_2 := 'eleven'.
            ].
            ((clone \\ 100) = 12) ifTrue: [
                part_2 := 'twelve'.
            ].
            ((clone \\ 100) = 13) ifTrue: [
                part_2 := 'thirteen'.
            ].
            ((clone \\ 100) = 14) ifTrue: [
                part_2 := 'fourteen'.
            ].
            ((clone \\ 100) = 15) ifTrue: [
                part_2 := 'fifteen'.
            ].
            ((clone \\ 100) = 16) ifTrue: [
                part_2 := 'sixteen'.
            ].
            ((clone \\ 100) = 17) ifTrue: [
                part_2 := 'seventeen'.
            ].
            ((clone \\ 100) = 18) ifTrue: [
                part_2 := 'eighteen'.
            ].
            ((clone \\ 100) = 19) ifTrue: [
                part_2 := 'nineteen'.
            ].
        ] ifFalse: [
            ((clone \\ 10) = 0) ifTrue: [
                part_1 := ''.
            ].
            ((clone \\ 10) = 1) ifTrue: [
                part_1 := 'one'.
            ].
            ((clone \\ 10) = 2) ifTrue: [
                part_1 := 'two'.
            ].
            ((clone \\ 10) = 3) ifTrue: [
                part_1 := 'three'.
            ].
            ((clone \\ 10) = 4) ifTrue: [
                part_1 := 'four'.
            ].
            ((clone \\ 10) = 5) ifTrue: [
                part_1 := 'five'.
            ].
            ((clone \\ 10) = 6) ifTrue: [
                part_1 := 'six'.
            ].
            ((clone \\ 10) = 7) ifTrue: [
                part_1 := 'seven'.
            ].
            ((clone \\ 10) = 8) ifTrue: [
                part_1 := 'eight'.
            ].
            ((clone \\ 10) = 9) ifTrue: [
                part_1 := 'nine'.
            ].
           
            clone := clone - (clone \\ 10).
           
            ((clone \\ 100) = 10) ifTrue: [
                part_2 := 'ten'.
            ].
            ((clone \\ 100) = 20) ifTrue: [
                part_2 := 'twenty'.
            ].
            ((clone \\ 100) = 30) ifTrue: [
                part_2 := 'thirty'.
            ].
            ((clone \\ 100) = 40) ifTrue: [
                part_2 := 'forty'.
            ].
            ((clone \\ 100) = 50) ifTrue: [
                part_2 := 'fifty'.
            ].
            ((clone \\ 100) = 60) ifTrue: [
                part_2 := 'sixty'.
            ].
            ((clone \\ 100) = 70) ifTrue: [
                part_2 := 'seventy'.
            ].
            ((clone \\ 100) = 80) ifTrue: [
                part_2 := 'eighty'.
            ].
            ((clone \\ 100) = 90) ifTrue: [
                part_2 := 'ninety'.
            ].
        ].
       
        ^part_2, part_1
    ]
]

Transcript show: (19 inWords)



_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Canol Gökel
Reply | Threaded
Open this post in threaded view
|

Re: Error while trying to write numbers in words

Olivier Blanc-3

Something is going on while interpreting the ifTrue:ifFalse: not sure
why... Paolo should be able to tell you what's going on.
In the mean time, you could try the following :

Number extend [
    inWords [
        | part_1 part_2 part_3 |
       
        part_1 := ''.
        part_2 := ''.
        part_3 := ''.

      ((self \\ 100) < 20 and: [(self \\ 100) > 10])
                ifTrue: [
                        part_2 := {'eleven'. 'twelve' . 'thirteen'. 'fourteen'. 'fifteen'.
'sixteen'. 'seventeen'. 'eighteen'. 'nineteen'} at: ((self \\ 100) -
10) .
        ]
                ifFalse: [
                        part_1 := {''. 'one'. 'two'. 'three'. 'four'. 'five'. 'six'. 'seven'.
'eight'. 'nine'} at: ((self \\ 10) + 1).
                                   part_2 := {'' . 'ten'. 'twenty'. 'thirty'. 'forty'. 'fifty'.
'sixty'. 'seventy'. 'eighty'. 'ninety'. 'hundred'} at: ((self // 10) +
1).
        ].
        ^part_2, part_1
    ]
]

(1 to: 99) do: [:i | Transcript show: i inWords; nl]

Regards,

Olivier


Le samedi 05 juillet 2008 à 17:15 +0000, Canol Gokel a écrit :

> Hello,
>
> I am trying to write a method called "inWords" for Number class to write a
> number in words. For example:
>
> 15 inWords
>
> should output:
>
> fifteen
>
> I wrote a code, it works for every 2 digit number except 19, for which it
> outputs "tennine". I guess there is a logic error in algorithm but I cannot find
> it. Anyone has an idea? Here is the code:
>
> Number extend [
>     inWords [
>         | clone part_1 part_2 part_3 |
>        
>         part_1 := ''.
>         part_2 := ''.
>         part_3 := ''.
>
>         clone := self copy.
>        
>         ((clone \\ 100) = 0) ifTrue: [
>             part_1 := ''.
>             part_2 := ''.
>         ].
>         ((clone \\ 100) < 20 and: [(clone \\ 100) > 10]) ifTrue: [
>             ((clone \\ 100) = 11) ifTrue: [
>                 part_2 := 'eleven'.
>             ].
>             ((clone \\ 100) = 12) ifTrue: [
>                 part_2 := 'twelve'.
>             ].
>             ((clone \\ 100) = 13) ifTrue: [
>                 part_2 := 'thirteen'.
>             ].
>             ((clone \\ 100) = 14) ifTrue: [
>                 part_2 := 'fourteen'.
>             ].
>             ((clone \\ 100) = 15) ifTrue: [
>                 part_2 := 'fifteen'.
>             ].
>             ((clone \\ 100) = 16) ifTrue: [
>                 part_2 := 'sixteen'.
>             ].
>             ((clone \\ 100) = 17) ifTrue: [
>                 part_2 := 'seventeen'.
>             ].
>             ((clone \\ 100) = 18) ifTrue: [
>                 part_2 := 'eighteen'.
>             ].
>             ((clone \\ 100) = 19) ifTrue: [
>                 part_2 := 'nineteen'.
>             ].
>         ] ifFalse: [
>             ((clone \\ 10) = 0) ifTrue: [
>                 part_1 := ''.
>             ].
>             ((clone \\ 10) = 1) ifTrue: [
>                 part_1 := 'one'.
>             ].
>             ((clone \\ 10) = 2) ifTrue: [
>                 part_1 := 'two'.
>             ].
>             ((clone \\ 10) = 3) ifTrue: [
>                 part_1 := 'three'.
>             ].
>             ((clone \\ 10) = 4) ifTrue: [
>                 part_1 := 'four'.
>             ].
>             ((clone \\ 10) = 5) ifTrue: [
>                 part_1 := 'five'.
>             ].
>             ((clone \\ 10) = 6) ifTrue: [
>                 part_1 := 'six'.
>             ].
>             ((clone \\ 10) = 7) ifTrue: [
>                 part_1 := 'seven'.
>             ].
>             ((clone \\ 10) = 8) ifTrue: [
>                 part_1 := 'eight'.
>             ].
>             ((clone \\ 10) = 9) ifTrue: [
>                 part_1 := 'nine'.
>             ].
>            
>             clone := clone - (clone \\ 10).
>            
>             ((clone \\ 100) = 10) ifTrue: [
>                 part_2 := 'ten'.
>             ].
>             ((clone \\ 100) = 20) ifTrue: [
>                 part_2 := 'twenty'.
>             ].
>             ((clone \\ 100) = 30) ifTrue: [
>                 part_2 := 'thirty'.
>             ].
>             ((clone \\ 100) = 40) ifTrue: [
>                 part_2 := 'forty'.
>             ].
>             ((clone \\ 100) = 50) ifTrue: [
>                 part_2 := 'fifty'.
>             ].
>             ((clone \\ 100) = 60) ifTrue: [
>                 part_2 := 'sixty'.
>             ].
>             ((clone \\ 100) = 70) ifTrue: [
>                 part_2 := 'seventy'.
>             ].
>             ((clone \\ 100) = 80) ifTrue: [
>                 part_2 := 'eighty'.
>             ].
>             ((clone \\ 100) = 90) ifTrue: [
>                 part_2 := 'ninety'.
>             ].
>         ].
>        
>         ^part_2, part_1
>     ]
> ]
>
> Transcript show: (19 inWords)
>
>
>
> _______________________________________________
> help-smalltalk mailing list
> [hidden email]
> http://lists.gnu.org/mailman/listinfo/help-smalltalk
>




_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: Error while trying to write numbers in words

ZuLuuuuuu
olivier blanc <olivier.blanc <at> laposte.net> writes:

>
> Something is going on while interpreting the ifTrue:ifFalse: not sure
> why...

Yes, it executes the ifFalse: part when it comes to 19 but I don't know why...

> In the mean time, you could try the following :
>
> Regards,
>
> Olivier

Thank you very much, your code is working!



_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Canol Gökel
Reply | Threaded
Open this post in threaded view
|

Re: Error while trying to write numbers in words

Paolo Bonzini-2
In reply to this post by ZuLuuuuuu
Canol Gokel wrote:

> Hello,
>
> I am trying to write a method called "inWords" for Number class to write a
> number in words. For example:
>
> 15 inWords
>
> should output:
>
> fifteen
>
> I wrote a code, it works for every 2 digit number except 19, for which it
> outputs "tennine". I guess there is a logic error in algorithm but I cannot find
> it.

No, it's my bug.  I'm sorry. :-(

Paolo


_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: Error while trying to write numbers in words

olivier blanc-4
Hi Paolo,

I couldn't find a way to point out where the bug is appearing.
How do you trace it down ?

Olivier

Le jeudi 10 juillet 2008 à 15:22 +0200, Paolo Bonzini a écrit :

> Canol Gokel wrote:
> > Hello,
> >
> > I am trying to write a method called "inWords" for Number class to write a
> > number in words. For example:
> >
> > 15 inWords
> >
> > should output:
> >
> > fifteen
> >
> > I wrote a code, it works for every 2 digit number except 19, for which it
> > outputs "tennine". I guess there is a logic error in algorithm but I cannot find
> > it.
>
> No, it's my bug.  I'm sorry. :-(
>
> Paolo
>
>
> _______________________________________________
> help-smalltalk mailing list
> [hidden email]
> http://lists.gnu.org/mailman/listinfo/help-smalltalk



_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: Error while trying to write numbers in words

Paolo Bonzini-2
Olivier Blanc wrote:
> Hi Paolo,
>
> I couldn't find a way to point out where the bug is appearing.
> How do you trace it down ?

I modified a little the code (just to make it more similar to my
Smalltalk coding style), and got a "stack height mismatch", which hints
to a bug in the compiler.

Alternatively, you can use -E to do an execution trace (I didn't try
that, but it should point to something very weird).

Paolo


_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: Error while trying to write numbers in words

Paolo Bonzini-2
Paolo Bonzini wrote:
> Olivier Blanc wrote:
>> Hi Paolo,
>>
>> I couldn't find a way to point out where the bug is appearing.
>> How do you trace it down ?
>
> I modified a little the code (just to make it more similar to my
> Smalltalk coding style), and got a "stack height mismatch", which hints
> to a bug in the compiler.

In the bytecode optimizer, more precisely.  The optimization of
jumps-to-jumps was causing a jump with a small range (<256 bytes) to
become a jump with a large range (>256 bytes), and the optimizer was
truncating the jump.

I fixed this in 43baff3b8586cae9cb505e8d3bc43c7915d4aa28 by more or less
rewriting the bytecode optimizer (_gst_optimize_bytecodes).

Then I noticed a speedup opportunity, because the optimizer was not
generating a few bytecodes that are in the bytecode set.  These are
"compound" bytecodes such as this one

   101 = bytecode bc101 {
     PREFETCH ();
     DUP_STACK_TOP ();
     POP_JUMP_FALSE (arg);
   }

(used in compiling #and: and #or: messages), this one

   165 = bytecode bc165 {
     PREFETCH ();
     NOT_NIL_SPECIAL ();
     POP_JUMP_FALSE (arg);
   }

(resulting from "a notNil ifTrue: [...]"), and this one

   134 = bytecode bc134 {
     ADVANCE ();
     POP_STACK_TOP ();
     JUMP_BACK (arg);
   }

(used in compiling #whileTrue: and #whileFalse: messages).  Generation
of these bytecodes is now done, after these three commits:

- 9bc2bf594fd75b4bbc02f4a13b421f545d507880 (a bug fix in the printing of
CompiledMethods)

- 18c63d0a2fcb677f176c30dd933366172f81a328 (bugs in the implementation
of the bytecodes that went unnoticed until now)

- 5aa9ebc511af8bd0615d3fb9e10198d145c22098 (actual generation of the
bytecodes in the optimizer)

I applied all four patches to the 3.0 branch too.  Should there be
problems, on the branch I might revert the last one or two.

Paolo


_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk