Hello,
For a exercism challenge I need to calculate the total grains on a chessboard. So I did : atSquare: anInteger self validateInput: anInteger. ^ anInteger = 1 ifTrue: [ 1 ] ifFalse: [ 2 * (self atSquare: anInteger - 1) ] but when I run the tests , the vm seems to be not responsive for some 4 - 5 seconds. Is there a way I can use this code and take care that the vm stays responsive. Regards, Roelof |
You can wrap the whole thing in a block and execute it in the background. Look for uses of fork: or forkAt:
Joachim > Am 04.01.2020 um 18:46 schrieb Roelof Wobben via Pharo-users <[hidden email]>: > > <mime-attachment> |
Administrator
|
In reply to this post by Pharo Smalltalk Users mailing list
On Sat, Jan 4, 2020 at 9:47 AM Roelof Wobben via Pharo-users <[hidden email]> wrote: Hello, What do you want the VM to do in addition to calculating that sum while it is calculating that sum? The best way to keep the VM responsive is to take a page from Gauss' notebook and pay attention to the numbers[1]. Let's consider the first four squares and extrapolate from there. In binary, the squares hold the following grains: 2r1, 2r10, r2100, and 2r1000. When we add them up, we get 2r1111. If we use Gauss' tricks, we can notice that 2r1111 is equal to 2r10000 - 1. So, the sum of the grains on the first 4 squares is 2^5 - 1. You can easily generalize that pattern, of course. Then your program can calculate the answer quickly. [1] The story goes that Gauss' teacher was frustrated with his student's abilities and set him a challenge to occupy him for some time: sum the numbers from 1 through 100. Gauss immediately answered 5,050, much to his teacher's chagrin.
|
Oke,
So I can better not use recursion for this problem if I understand you well, Richard. Roelof Op 4-1-2020 om 19:02 schreef Richard Sargent:
|
Administrator
|
On Sat, Jan 4, 2020 at 10:37 AM Roelof Wobben via Pharo-users <[hidden email]> wrote:
That is oversimplifying. If the purpose of the *training* *exercise* is to learn how to use recursion, then using recursion is a necessary thing. If the purpose of the exercise is to solve a problem, understanding whether there are more efficient approaches to the solution is an essential skill. This particular problem could have been solved using a recursive implementation, an iterative implementation, or a fundamental reframing of the problem to change it to an O(1) problem. Other problems are no so simply reframed. One of the most important skills you will ever develop is to understand that a request for a feature may not be accurately describing the problem. A feature request is often a description of a problem from a single perspective. Learning to recognize whether it is one or the other will be crucial to your long-term success as a programmer.
|
Richard Sargent wrote
> One of the most important skills you will ever develop is to understand > that a request for a feature may not be accurately describing the problem. > A feature request is often a description of a problem from a single > perspective. Learning to recognize whether it is one or the other will be > crucial to your long-term success as a programmer. Well put. I would add a couple of others: Being able to interpret & re-interpret feature requests, given that they are often poorly and incompletely specified; this requires closing the loop with the customer to ensure that your mutual understanding is spelled out clearly and agreed to. Another is being able to skillfully negotiate feature and implementation details with the customer to arrive at a requirements specification that not only satisfies the customer's needs, but also specifies a system that you can actually implement -- given the allotted schedule & budget and the capabilities of your tools and team (which of course includes your own know-how). -t -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html |
In reply to this post by Richard Sargent
Thanks for the lessson and its correct
that English is not my mother language. Im from the Netherlands
and were very bad at languages but good at math, science and that
sort of things at school.
Some of the names as squareAt: were given by the exercism challenge. The things you said about the computer challenge which was a AdventOfCode one I agree. im still not happy with my answer at this moment. For me at this point , its something a puzzle to find a way to make the code to solve things that I do not spend and think a lot about names. That is why I asked here a few times on a mentor which can learn me how to solve things like the computer one the smalltalk way but it seems that every one is very busy with thier own projects and work, which I understand but for my feeling I do not come to a higher level to understand OOP and things like how to solve things the smalltalk way and also learn more how to name things better. As you hint to use a person to explain it to me , I do not have. My wife works full-time and has at the evening no time to help me with this. So im now in a doubt if I want to go on with smalltalk, which I find a pity because I love it. But on solving this sort of puzzles and learning how to make my own websie in seaside , i get the feeling my learning is coming to a still stand. Also enoough rambling on this side. Roelof Op 4-1-2020 om 22:11 schreef Richard Sargent:
|
Administrator
|
Pharo Smalltalk Users mailing list wrote
> im still not happy with my answer at this moment. Contrary to the delusion of "Learn [Programming Language] in 21 Days" or 7 minutes or 3 seconds or whatever the "code boot camps" are marketing these days, mastering any language (and by extension programming in general) probably will take a decade and countless hours. I wouldn't get hung up on making this one exercise perfect. If it accomplishes the task, move on to the next learning experiment. Everyone is trying to help, but you don't have to assimilate this entire pile of great advice in one day! Come back to this thread after a year of practice and you'll likely be shocked how much more sense these comments make :) ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Cheers,
Sean |
Sean, I hope your comment doesn't discourage Roelof! I might agree that
"mastery" of a given programming language could take a decade of working with it, but it doesn't take anywhere near that long to "learn" a programming language. There are other factors, such as whether or not you already know at least one language: you'll associate what you already know with the new ways of doing the same sorts of things. And you'll know to look for things that you can reasonably expect a new language to provide. But the first language you learn will probably take the longest time, as expected. I think learning Smalltalk/Pharo will take longer than you might expect if the other languages you know are procedural or functional, rather than object-oriented: You need to learn a new way of thinking when learning OOP for the first time. And that can be hard! As humans, we're probably "hard-wired" to think procedurally, which can be a bit of a handicap you when starting OOP. You don't need to, and shouldn't expect to be able to learn everything about a programming language immediately, as you begin learning it. Once you learn the basics (enough to start writing programs that "do something"), you need to begin writing programs --frequently-- and then begin the process of incrementally adding to your understanding and knowledge of "the finer details". You learn as you go. Reading up on the subject, including reading others' code, helps a lot as well. Today we have GitHub to help there! Don't give up, Roelof. The struggles you go through now tell you that you've progressed to the stage of "being aware of what you don't know", which is good: It leads you to ask the right questions that will expand your knowledge. Finding the answers will sometimes be a challenge, but "mastery" of a language pretty much always requires that you work through the kinds of problems you've been having. It's what gives you "insight", summed up as "been there, done that". Otherwise your knowledge of the language would only be superficial (e.g., you would be able to read code examples, but you wouldn't be able to code the examples on your own). We've all been through these kinds of struggles you're having now. It's part of the process, not an indication of "you can't do it". As Sean says, after a year of working with Pharo, you'll be offering the same kinds of advice to others that will follow you in getting started. Just keep at it! -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html |
Thanks.
I know that im at that stage and like I said I have the feeling that Im at the stage for more then a half year. I think I know a lot of pieces but need some help to see how the pieces could help me to solve the more complex problems. But maybe I want to fast and I need to concentrate on simple websites with seaside first and the problems of exercism and let the problems of Advent of Code to a later point when I have more experience. I know that the problems of Exercism are from easy to hard and maybe that is a better way. Roelof Op 5-1-2020 om 03:34 schreef tbrunz: > Sean, I hope your comment doesn't discourage Roelof! I might agree that > "mastery" of a given programming language could take a decade of working > with it, but it doesn't take anywhere near that long to "learn" a > programming language. > > There are other factors, such as whether or not you already know at least > one language: you'll associate what you already know with the new ways of > doing the same sorts of things. And you'll know to look for things that you > can reasonably expect a new language to provide. But the first language you > learn will probably take the longest time, as expected. > > I think learning Smalltalk/Pharo will take longer than you might expect if > the other languages you know are procedural or functional, rather than > object-oriented: You need to learn a new way of thinking when learning OOP > for the first time. And that can be hard! As humans, we're probably > "hard-wired" to think procedurally, which can be a bit of a handicap you > when starting OOP. > > You don't need to, and shouldn't expect to be able to learn everything about > a programming language immediately, as you begin learning it. Once you > learn the basics (enough to start writing programs that "do something"), you > need to begin writing programs --frequently-- and then begin the process of > incrementally adding to your understanding and knowledge of "the finer > details". You learn as you go. Reading up on the subject, including > reading others' code, helps a lot as well. Today we have GitHub to help > there! > > Don't give up, Roelof. The struggles you go through now tell you that > you've progressed to the stage of "being aware of what you don't know", > which is good: It leads you to ask the right questions that will expand your > knowledge. Finding the answers will sometimes be a challenge, but "mastery" > of a language pretty much always requires that you work through the kinds of > problems you've been having. It's what gives you "insight", summed up as > "been there, done that". Otherwise your knowledge of the language would > only be superficial (e.g., you would be able to read code examples, but you > wouldn't be able to code the examples on your own). > > We've all been through these kinds of struggles you're having now. It's > part of the process, not an indication of "you can't do it". As Sean says, > after a year of working with Pharo, you'll be offering the same kinds of > advice to others that will follow you in getting started. Just keep at it! > > > > -- > Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html > > |
In reply to this post by Pharo Smalltalk Users mailing list
Time microsecondsToRun: [
|n| n := (2 raisedToInteger: 8 * 8) - 1. Transcript nextPutAll: 'The number of grains on an 8x8 chessboard is '; print: n; cr; endEntry]. <PRINT-IT> On my laptop, this reports 194 microseconds. Why would you use recursion, anyway? Time microsecondsToRun: [ |n| n := (1 to: 8 * 8) inject: 0 into: [:acc :each | acc+acc+1]. Transcript nextPutAll: 'The number of grains on an 8x8 chessboard is '; print: n; cr; endEntry]. <PRINT-IT> On the same laptop, this reports 118 microseconds. One of the lessons of 'functional' languages, promptly adopted by Smalltalk, is to encapsulate control structures into reusable methods, such as #inject:into:, more commonly known as `foldl` in functional languages. It's then none of my business whether such a method works by recursion, iteration, or gangs of otherwise seasonally unemployed Christmas elves. In my own Smalltalk library, (GeometricSeries new: 64 from: 1 byFactor: 2) sum only takes 15 microseconds. I do note that you are calling validateInput repeatedly. Why? On Sun, 5 Jan 2020 at 07:41, Roelof Wobben via Pharo-users <[hidden email]> wrote: > > Oke, > > So I can better not use recursion for this problem if I understand you well, Richard. > > Roelof > > > > Op 4-1-2020 om 19:02 schreef Richard Sargent: > > On Sat, Jan 4, 2020 at 9:47 AM Roelof Wobben via Pharo-users <[hidden email]> wrote: >> >> Hello, >> >> For a exercism challenge I need to calculate the total grains on a >> chessboard. >> So I did : >> >> atSquare: anInteger >> self validateInput: anInteger. >> ^ anInteger = 1 >> ifTrue: [ 1 ] >> ifFalse: [ 2 * (self atSquare: anInteger - 1) ] >> >> >> but when I run the tests , the vm seems to be not responsive for some 4 >> - 5 seconds. >> >> Is there a way I can use this code and take care that the vm stays >> responsive. > > > What do you want the VM to do in addition to calculating that sum while it is calculating that sum? > > > The best way to keep the VM responsive is to take a page from Gauss' notebook and pay attention to the numbers[1]. Let's consider the first four squares and extrapolate from there. > > In binary, the squares hold the following grains: 2r1, 2r10, r2100, and 2r1000. When we add them up, we get 2r1111. If we use Gauss' tricks, we can notice that 2r1111 is equal to 2r10000 - 1. So, the sum of the grains on the first 4 squares is 2^5 - 1. You can easily generalize that pattern, of course. Then your program can calculate the answer quickly. > > > [1] The story goes that Gauss' teacher was frustrated with his student's abilities and set him a challenge to occupy him for some time: sum the numbers from 1 through 100. Gauss immediately answered 5,050, much to his teacher's chagrin. > >> >> Regards, >> >> Roelof >> >> > |
Hello Ricard.
You mean when I calcualate the total of a board. That is because on when I had to calculate the number of a particular field there were tests where the number was lower then zero or higher then 64 which makes no sense. But im open for a solution where on a particular field I could check for that and for the total I do not need that part. Roelof Op 5-1-2020 om 13:58 schreef Richard O'Keefe: > Time microsecondsToRun: [ > |n| > n := (2 raisedToInteger: 8 * 8) - 1. > Transcript > nextPutAll: 'The number of grains on an 8x8 chessboard is '; > print: n; cr; endEntry]. > <PRINT-IT> > On my laptop, this reports 194 microseconds. > > Why would you use recursion, anyway? > > Time microsecondsToRun: [ > |n| > n := (1 to: 8 * 8) inject: 0 into: [:acc :each | acc+acc+1]. > Transcript > nextPutAll: 'The number of grains on an 8x8 chessboard is '; > print: n; cr; endEntry]. > <PRINT-IT> > On the same laptop, this reports 118 microseconds. > > One of the lessons of 'functional' languages, promptly adopted by Smalltalk, is > to encapsulate control structures into reusable methods, such as #inject:into:, > more commonly known as `foldl` in functional languages. It's then none of > my business whether such a method works by recursion, iteration, or gangs > of otherwise seasonally unemployed Christmas elves. > > In my own Smalltalk library, > (GeometricSeries new: 64 from: 1 byFactor: 2) sum > only takes 15 microseconds. > > I do note that you are calling validateInput repeatedly. Why? > > > On Sun, 5 Jan 2020 at 07:41, Roelof Wobben via Pharo-users > <[hidden email]> wrote: >> Oke, >> >> So I can better not use recursion for this problem if I understand you well, Richard. >> >> Roelof >> >> >> >> Op 4-1-2020 om 19:02 schreef Richard Sargent: >> >> On Sat, Jan 4, 2020 at 9:47 AM Roelof Wobben via Pharo-users <[hidden email]> wrote: >>> Hello, >>> >>> For a exercism challenge I need to calculate the total grains on a >>> chessboard. >>> So I did : >>> >>> atSquare: anInteger >>> self validateInput: anInteger. >>> ^ anInteger = 1 >>> ifTrue: [ 1 ] >>> ifFalse: [ 2 * (self atSquare: anInteger - 1) ] >>> >>> >>> but when I run the tests , the vm seems to be not responsive for some 4 >>> - 5 seconds. >>> >>> Is there a way I can use this code and take care that the vm stays >>> responsive. >> >> What do you want the VM to do in addition to calculating that sum while it is calculating that sum? >> >> >> The best way to keep the VM responsive is to take a page from Gauss' notebook and pay attention to the numbers[1]. Let's consider the first four squares and extrapolate from there. >> >> In binary, the squares hold the following grains: 2r1, 2r10, r2100, and 2r1000. When we add them up, we get 2r1111. If we use Gauss' tricks, we can notice that 2r1111 is equal to 2r10000 - 1. So, the sum of the grains on the first 4 squares is 2^5 - 1. You can easily generalize that pattern, of course. Then your program can calculate the answer quickly. >> >> >> [1] The story goes that Gauss' teacher was frustrated with his student's abilities and set him a challenge to occupy him for some time: sum the numbers from 1 through 100. Gauss immediately answered 5,050, much to his teacher's chagrin. >> >>> Regards, >>> >>> Roelof >>> >>> |
In reply to this post by Richard O'Keefe
I did not ask why you were validating input.
I asked about why you *repeatedly* validated input. Think of it this way: publicMethod: arg1 also: arg2 ... check arg1 ... ... check arg2 ... ^self privateMethod: arg1 also: arg2 privateMethod: arg1 also: arg2 ... trust that arg1 and arg2 are valide ... ... recursive calls use #privateMethod:andAlso: ... ... not #publicMethod:andAlso: and must ensure ... ... that arguments are valid by construction ... In my solution to the "Grains" exercism, I have atSquare: n -- checks its argument total ^(1 bitShift: 64) - 1 You are required to implement these two methods, true. You are NOT required to implement #total by calling #atSquare:. Not even once. Nor is #atSquare: required to be recursive. On Mon, 6 Jan 2020 at 02:05, Roelof Wobben <[hidden email]> wrote: > > Hello Ricard. > > You mean when I calcualate the total of a board. > That is because on when I had to calculate the number of a particular > field there were tests where the number was lower then zero or higher > then 64 which makes no sense. > > But im open for a solution where on a particular field I could check for > that and for the total I do not need that part. > > Roelof > > > > Op 5-1-2020 om 13:58 schreef Richard O'Keefe: > > Time microsecondsToRun: [ > > |n| > > n := (2 raisedToInteger: 8 * 8) - 1. > > Transcript > > nextPutAll: 'The number of grains on an 8x8 chessboard is '; > > print: n; cr; endEntry]. > > <PRINT-IT> > > On my laptop, this reports 194 microseconds. > > > > Why would you use recursion, anyway? > > > > Time microsecondsToRun: [ > > |n| > > n := (1 to: 8 * 8) inject: 0 into: [:acc :each | acc+acc+1]. > > Transcript > > nextPutAll: 'The number of grains on an 8x8 chessboard is '; > > print: n; cr; endEntry]. > > <PRINT-IT> > > On the same laptop, this reports 118 microseconds. > > > > One of the lessons of 'functional' languages, promptly adopted by Smalltalk, is > > to encapsulate control structures into reusable methods, such as #inject:into:, > > more commonly known as `foldl` in functional languages. It's then none of > > my business whether such a method works by recursion, iteration, or gangs > > of otherwise seasonally unemployed Christmas elves. > > > > In my own Smalltalk library, > > (GeometricSeries new: 64 from: 1 byFactor: 2) sum > > only takes 15 microseconds. > > > > I do note that you are calling validateInput repeatedly. Why? > > > > > > On Sun, 5 Jan 2020 at 07:41, Roelof Wobben via Pharo-users > > <[hidden email]> wrote: > >> Oke, > >> > >> So I can better not use recursion for this problem if I understand you well, Richard. > >> > >> Roelof > >> > >> > >> > >> Op 4-1-2020 om 19:02 schreef Richard Sargent: > >> > >> On Sat, Jan 4, 2020 at 9:47 AM Roelof Wobben via Pharo-users <[hidden email]> wrote: > >>> Hello, > >>> > >>> For a exercism challenge I need to calculate the total grains on a > >>> chessboard. > >>> So I did : > >>> > >>> atSquare: anInteger > >>> self validateInput: anInteger. > >>> ^ anInteger = 1 > >>> ifTrue: [ 1 ] > >>> ifFalse: [ 2 * (self atSquare: anInteger - 1) ] > >>> > >>> > >>> but when I run the tests , the vm seems to be not responsive for some 4 > >>> - 5 seconds. > >>> > >>> Is there a way I can use this code and take care that the vm stays > >>> responsive. > >> > >> What do you want the VM to do in addition to calculating that sum while it is calculating that sum? > >> > >> > >> The best way to keep the VM responsive is to take a page from Gauss' notebook and pay attention to the numbers[1]. Let's consider the first four squares and extrapolate from there. > >> > >> In binary, the squares hold the following grains: 2r1, 2r10, r2100, and 2r1000. When we add them up, we get 2r1111. If we use Gauss' tricks, we can notice that 2r1111 is equal to 2r10000 - 1. So, the sum of the grains on the first 4 squares is 2^5 - 1. You can easily generalize that pattern, of course. Then your program can calculate the answer quickly. > >> > >> > >> [1] The story goes that Gauss' teacher was frustrated with his student's abilities and set him a challenge to occupy him for some time: sum the numbers from 1 through 100. Gauss immediately answered 5,050, much to his teacher's chagrin. > >> > >>> Regards, > >>> > >>> Roelof > >>> > >>> > |
There you are right but the hint we get was thinking about recursion
but your lessons showed me other ways to do it which I think are more the way smalltalk works, Thanks for that. Roelof Op 5-1-2020 om 14:24 schreef Richard O'Keefe: > I did not ask why you were validating input. > I asked about why you *repeatedly* validated input. > > Think of it this way: > publicMethod: arg1 also: arg2 > ... check arg1 ... > ... check arg2 ... > ^self privateMethod: arg1 also: arg2 > > privateMethod: arg1 also: arg2 > ... trust that arg1 and arg2 are valide ... > ... recursive calls use #privateMethod:andAlso: ... > ... not #publicMethod:andAlso: and must ensure ... > ... that arguments are valid by construction ... > > In my solution to the "Grains" exercism, I have > atSquare: n -- checks its argument > total ^(1 bitShift: 64) - 1 > You are required to implement these two methods, true. > You are NOT required to implement #total by calling #atSquare:. > Not even once. Nor is #atSquare: required to be recursive. > > On Mon, 6 Jan 2020 at 02:05, Roelof Wobben <[hidden email]> wrote: >> Hello Ricard. >> >> You mean when I calcualate the total of a board. >> That is because on when I had to calculate the number of a particular >> field there were tests where the number was lower then zero or higher >> then 64 which makes no sense. >> >> But im open for a solution where on a particular field I could check for >> that and for the total I do not need that part. >> >> Roelof >> >> >> >> Op 5-1-2020 om 13:58 schreef Richard O'Keefe: >>> Time microsecondsToRun: [ >>> |n| >>> n := (2 raisedToInteger: 8 * 8) - 1. >>> Transcript >>> nextPutAll: 'The number of grains on an 8x8 chessboard is '; >>> print: n; cr; endEntry]. >>> <PRINT-IT> >>> On my laptop, this reports 194 microseconds. >>> >>> Why would you use recursion, anyway? >>> >>> Time microsecondsToRun: [ >>> |n| >>> n := (1 to: 8 * 8) inject: 0 into: [:acc :each | acc+acc+1]. >>> Transcript >>> nextPutAll: 'The number of grains on an 8x8 chessboard is '; >>> print: n; cr; endEntry]. >>> <PRINT-IT> >>> On the same laptop, this reports 118 microseconds. >>> >>> One of the lessons of 'functional' languages, promptly adopted by Smalltalk, is >>> to encapsulate control structures into reusable methods, such as #inject:into:, >>> more commonly known as `foldl` in functional languages. It's then none of >>> my business whether such a method works by recursion, iteration, or gangs >>> of otherwise seasonally unemployed Christmas elves. >>> >>> In my own Smalltalk library, >>> (GeometricSeries new: 64 from: 1 byFactor: 2) sum >>> only takes 15 microseconds. >>> >>> I do note that you are calling validateInput repeatedly. Why? >>> >>> >>> On Sun, 5 Jan 2020 at 07:41, Roelof Wobben via Pharo-users >>> <[hidden email]> wrote: >>>> Oke, >>>> >>>> So I can better not use recursion for this problem if I understand you well, Richard. >>>> >>>> Roelof >>>> >>>> >>>> >>>> Op 4-1-2020 om 19:02 schreef Richard Sargent: >>>> >>>> On Sat, Jan 4, 2020 at 9:47 AM Roelof Wobben via Pharo-users <[hidden email]> wrote: >>>>> Hello, >>>>> >>>>> For a exercism challenge I need to calculate the total grains on a >>>>> chessboard. >>>>> So I did : >>>>> >>>>> atSquare: anInteger >>>>> self validateInput: anInteger. >>>>> ^ anInteger = 1 >>>>> ifTrue: [ 1 ] >>>>> ifFalse: [ 2 * (self atSquare: anInteger - 1) ] >>>>> >>>>> >>>>> but when I run the tests , the vm seems to be not responsive for some 4 >>>>> - 5 seconds. >>>>> >>>>> Is there a way I can use this code and take care that the vm stays >>>>> responsive. >>>> What do you want the VM to do in addition to calculating that sum while it is calculating that sum? >>>> >>>> >>>> The best way to keep the VM responsive is to take a page from Gauss' notebook and pay attention to the numbers[1]. Let's consider the first four squares and extrapolate from there. >>>> >>>> In binary, the squares hold the following grains: 2r1, 2r10, r2100, and 2r1000. When we add them up, we get 2r1111. If we use Gauss' tricks, we can notice that 2r1111 is equal to 2r10000 - 1. So, the sum of the grains on the first 4 squares is 2^5 - 1. You can easily generalize that pattern, of course. Then your program can calculate the answer quickly. >>>> >>>> >>>> [1] The story goes that Gauss' teacher was frustrated with his student's abilities and set him a challenge to occupy him for some time: sum the numbers from 1 through 100. Gauss immediately answered 5,050, much to his teacher's chagrin. >>>> >>>>> Regards, >>>>> >>>>> Roelof >>>>> >>>>> |
In reply to this post by Richard O'Keefe
Hi Richard, Just fyi, the aim of Exercism is not to teach programming. Its aim is for experienced programmers to fast-start in new languages. It just happens to that new programmers also use Exercism and there is some catering in the exercise text for this. The grains exercise provides a nice vehicle for programmers to familiarize themselves with recursion in Pharo, and the hint for the exercise says "These kinds of problems (where an answer is dependent on a previous) one are often called recursion" which is why Roelof is approaching the problem this way. That said, any solution will do. Your advice on alternative considerations is insightful and always good to read. cheers -ben On Mon, 6 Jan 2020 at 00:25, Richard O'Keefe <[hidden email]> wrote: I did not ask why you were validating input. |
Well, no. This is not a particularly "nice vehicle for programmers to
familiarise themselves with recursion". To start with, a quick web search turns up https://en.wikipedia.org/wiki/Wheat_and_chessboard_problem. Problems where the result depend on previous results often fall into the "dynamic programming" category, with Object subclass: #ChessBoard instanceVariableNames: 'board sum' class methods for: 'instance creation' new: n ^self new initialize: n methods for: 'initializing; initialize: n board := Array new: n squared. board at: 1 put: 1. 2 to: board size do: [:i | board at: i put: (board at: i - 1) * 2]. sum := 0. board do: [:each | sum := sum + each]. ^self methods for: 'accessing' squareAt: i ^board at: i total ^sum being the most obvious elementary implementation. The very description of the problem suggests an iterative approach. To find a nice problem for recursion, you have to find one where tabulation is *not* a good strategy. On Mon, 6 Jan 2020 at 08:06, Ben Coman <[hidden email]> wrote: > > Hi Richard, > > Just fyi, the aim of Exercism is not to teach programming. Its aim is for experienced programmers to fast-start in new languages. > It just happens to that new programmers also use Exercism and there is some catering in the exercise text for this. > > The grains exercise provides a nice vehicle for programmers to familiarize themselves with recursion in Pharo, > and the hint for the exercise says "These kinds of problems (where an answer is dependent on a previous) one are often called recursion" > which is why Roelof is approaching the problem this way. > > That said, any solution will do. Your advice on alternative considerations is insightful and always good to read. > > cheers -ben > > On Mon, 6 Jan 2020 at 00:25, Richard O'Keefe <[hidden email]> wrote: >> >> I did not ask why you were validating input. >> I asked about why you *repeatedly* validated input. >> >> Think of it this way: >> publicMethod: arg1 also: arg2 >> ... check arg1 ... >> ... check arg2 ... >> ^self privateMethod: arg1 also: arg2 >> >> privateMethod: arg1 also: arg2 >> ... trust that arg1 and arg2 are valide ... >> ... recursive calls use #privateMethod:andAlso: ... >> ... not #publicMethod:andAlso: and must ensure ... >> ... that arguments are valid by construction ... >> >> In my solution to the "Grains" exercism, I have >> atSquare: n -- checks its argument >> total ^(1 bitShift: 64) - 1 >> You are required to implement these two methods, true. >> You are NOT required to implement #total by calling #atSquare:. >> Not even once. Nor is #atSquare: required to be recursive. >> >> On Mon, 6 Jan 2020 at 02:05, Roelof Wobben <[hidden email]> wrote: >> > >> > Hello Ricard. >> > >> > You mean when I calcualate the total of a board. >> > That is because on when I had to calculate the number of a particular >> > field there were tests where the number was lower then zero or higher >> > then 64 which makes no sense. >> > >> > But im open for a solution where on a particular field I could check for >> > that and for the total I do not need that part. >> > >> > Roelof >> > >> > >> > >> > Op 5-1-2020 om 13:58 schreef Richard O'Keefe: >> > > Time microsecondsToRun: [ >> > > |n| >> > > n := (2 raisedToInteger: 8 * 8) - 1. >> > > Transcript >> > > nextPutAll: 'The number of grains on an 8x8 chessboard is '; >> > > print: n; cr; endEntry]. >> > > <PRINT-IT> >> > > On my laptop, this reports 194 microseconds. >> > > >> > > Why would you use recursion, anyway? >> > > >> > > Time microsecondsToRun: [ >> > > |n| >> > > n := (1 to: 8 * 8) inject: 0 into: [:acc :each | acc+acc+1]. >> > > Transcript >> > > nextPutAll: 'The number of grains on an 8x8 chessboard is '; >> > > print: n; cr; endEntry]. >> > > <PRINT-IT> >> > > On the same laptop, this reports 118 microseconds. >> > > >> > > One of the lessons of 'functional' languages, promptly adopted by Smalltalk, is >> > > to encapsulate control structures into reusable methods, such as #inject:into:, >> > > more commonly known as `foldl` in functional languages. It's then none of >> > > my business whether such a method works by recursion, iteration, or gangs >> > > of otherwise seasonally unemployed Christmas elves. >> > > >> > > In my own Smalltalk library, >> > > (GeometricSeries new: 64 from: 1 byFactor: 2) sum >> > > only takes 15 microseconds. >> > > >> > > I do note that you are calling validateInput repeatedly. Why? >> > > >> > > >> > > On Sun, 5 Jan 2020 at 07:41, Roelof Wobben via Pharo-users >> > > <[hidden email]> wrote: >> > >> Oke, >> > >> >> > >> So I can better not use recursion for this problem if I understand you well, Richard. >> > >> >> > >> Roelof >> > >> >> > >> >> > >> >> > >> Op 4-1-2020 om 19:02 schreef Richard Sargent: >> > >> >> > >> On Sat, Jan 4, 2020 at 9:47 AM Roelof Wobben via Pharo-users <[hidden email]> wrote: >> > >>> Hello, >> > >>> >> > >>> For a exercism challenge I need to calculate the total grains on a >> > >>> chessboard. >> > >>> So I did : >> > >>> >> > >>> atSquare: anInteger >> > >>> self validateInput: anInteger. >> > >>> ^ anInteger = 1 >> > >>> ifTrue: [ 1 ] >> > >>> ifFalse: [ 2 * (self atSquare: anInteger - 1) ] >> > >>> >> > >>> >> > >>> but when I run the tests , the vm seems to be not responsive for some 4 >> > >>> - 5 seconds. >> > >>> >> > >>> Is there a way I can use this code and take care that the vm stays >> > >>> responsive. >> > >> >> > >> What do you want the VM to do in addition to calculating that sum while it is calculating that sum? >> > >> >> > >> >> > >> The best way to keep the VM responsive is to take a page from Gauss' notebook and pay attention to the numbers[1]. Let's consider the first four squares and extrapolate from there. >> > >> >> > >> In binary, the squares hold the following grains: 2r1, 2r10, r2100, and 2r1000. When we add them up, we get 2r1111. If we use Gauss' tricks, we can notice that 2r1111 is equal to 2r10000 - 1. So, the sum of the grains on the first 4 squares is 2^5 - 1. You can easily generalize that pattern, of course. Then your program can calculate the answer quickly. >> > >> >> > >> >> > >> [1] The story goes that Gauss' teacher was frustrated with his student's abilities and set him a challenge to occupy him for some time: sum the numbers from 1 through 100. Gauss immediately answered 5,050, much to his teacher's chagrin. >> > >> >> > >>> Regards, >> > >>> >> > >>> Roelof >> > >>> >> > >>> >> > >> |
Free forum by Nabble | Edit this page |