Op 1-5-2020 om 08:35 schreef Roelof Wobben:
Op 1-5-2020 om 02:51 schreef Richard O'Keefe:
(oddSum + evenSum) dividedBy: 10
You previously had _ isDivisibleBy: 10 which certainly works.
Squeak, Pharo, and ST/X have #isDivisibleBy: VisualWorks. Dolphin, and GNU Smalltalk do not.
Here's the code from Number.st in ST/X. isDivisibleBy:aNumber     "return true, if the receiver can be divided by the argument, aNumber without a remainder.      Notice, that the result is only worth trusting, if the receiver is an integer."
    aNumber = 0 ifTrue: [^ false].     aNumber isInteger ifFalse: [^ false].     ^ (self \\ aNumber) = 0
The comment is wrong: the question makes sense for any combination of exact numbers. When, as in this case, aNumber is a literal integer, all #isDivisibleBy: really adds is overhead.
(oddSum + evenSum) \\ 10 = 0
is quite clear, and completely portable.
On Fri, 1 May 2020 at 02:16, Roelof Wobben <r.wobben@home.nl> wrote:
Op 30-4-2020 om 16:06 schreef Richard O'Keefe:
This sounds very much like the Luhn test task at RosettaCode. https://rosettacode.org/wiki/Luhn_test_of_credit_card_numbers except that there it is described as working on the digits of an integer.
(1) There are two approaches to traversing a sequence in reverse.      (A) Reverse the sequence, then traverse the copy forward.          aString reverse do: [:each | ...]      (B) Just traverse the sequence in reverse          aString reverseDo: [:each | ...]      My taste is for the second.
(2) There are two approaches to deleting spaces. Â Â Â Â Â (A) Make a copy of the string without spaces. Â Â Â Â Â Â Â Â Â x := aString reject: [:each | each = Character space]. Â Â Â Â Â Â Â Â Â x do: ... Â Â Â Â Â (B) Ignore spaces as you go: Â Â Â Â Â Â Â Â Â (i) aString do: [:each | each = Character space ifFalse: [...]] Â Â Â Â Â Â Â Â Â (ii) aString select: [:each | each ~= Character space] thenDo: [:each | ...]
Combining (1A) and (2A) you get very obvious code: Â Â Â Â Â (aString reject: [:each | each = Character space]) reverse do: [:digit } ...] Combining (1B) and (2Bi) you get more efficient code: Â Â Â Â Â aString reverseDo: [:digit | Â Â Â Â Â Â Â Â Â digit = Character space ifFalse: [ ...]]
By the way, let's start by checking that the character in the string *are* digits or spaces: Â Â Â Â Â (aString allSatisfy: [:each | each isDigit or: [each = Character s[ace]]) Â Â Â Â Â Â Â Â Â ifFalse: [^false],
(3) There are two approaches to doubling the even digits.      (A) Make a new string that starts as a copy and change every second           digit from the right.      (B) Simply *act* as if this has been done; keep track of whether the          current digit position is even or odd and multiply by 1 or 2 as          appropriate.      nextIsOdd := true.      aString reverseDo: [:digit |          digit = Character space ifFalse: [          nextIsOdd              ifTrue: [oddSum := ...]              ifFalse: [evenSum := ...].          nextIsOdd := nextIsOdd not]].
I *like* code that traverses a data structure exactly once and allocates no intermediate garbage, so I'd be making (B) choices.
For me , I use this to practice solving problems and doing the "right" steps. So I love it , that so many people share there way of solving it. I can learn a lot from it Expecially when they explain there thinking process so detailed.
I like this code also a lot. Am I correct for testing if it is a valid string by doing this ^ (oddSum + evenSum) dividedBy: 10
Roelof
oke,
so this is better
cardNumber := '8273 1232 7352 0569'. oddSum := 0. evenSum := 0. nextIsOdd := false.     cardNumber reverseDo: [:character |         digit := character digitValue.         character = Character space ifFalse: [         nextIsOdd             ifFalse: [oddSum := oddSum + digit ]             ifTrue: [(digit >= 5 )    ifTrue: [evenSum := evenSum + (digit * 2) - 9 ]    ifFalse: [ evenSum := evenSum + (digit * 2) ]].            nextIsOdd := nextIsOdd not]]. ^ evenSum + oddSum // 10 == 0.
where I could even make a seperate method of the ifTrue branch when the digit is greater then 5.
nobody who can say if this is a good solution ? Roelof