1. Tight programming exercise, using bad programming practices
- Posted by fizzpopsoft Jun 18, 2015
- 2800 views
A friend who is studying, was asked to create pseudo-code for the following problem:
- Your algorithm should:
o Search a string of at least five numbers (for example, 37540)
o Identify all of the substrings that form numbers that are divisible by 3.
o For example, applying the algorithm on the string 37540 should produce the
following substrings (not necessarily in this order): 0; 3; 75; 54; 375; 540.
OK, did that for him, but just for the heck of it, I also provided the following code,
as an example of a few bad programming practices to see how small I could make it,
while still being mostly legible.
Other than making the two value related statements into one, can anyone make it smaller?
procedure tiny() sequence s1,s2,s3="37540" atom a1 integer i1,i2=0 while i2<5 do i2=i2+1 i1=i2-1 while i1<5 do i1=i1+1 s1=s3[i2..i1] s2=value(s1) a1=s2[2] if floor(a1/3)=(a1/3) then puts(1,s1&", ") end if end while end while end procedure tiny()
2. Re: Tight programming exercise, using bad programming practices
- Posted by petelomax Jun 18, 2015
- 2743 views
s3 should be a parameter and it should use length(s3) rather than 5. for loops ought to be slightly shorter. Using a bit of edit-fu I knocked up a quick table to help me visualize things:
r3 &0r3 &1r3 &2r3 &3r3 &4r3 &5r3 &6r3 &7r3 &8r3 &9r3 0 0 0 1 2 0 1 2 0 1 2 0 1 1 1 2 0 1 2 0 1 2 0 1 2 2 2 0 1 2 0 1 2 0 1 2 3 0 0 1 2 0 1 2 0 1 2 0 4 1 1 2 0 1 2 0 1 2 0 1 5 2 2 0 1 2 0 1 2 0 1 2 6 0 0 1 2 0 1 2 0 1 2 0 7 1 1 2 0 1 2 0 1 2 0 1 8 2 2 0 1 2 0 1 2 0 1 2 9 0 0 1 2 0 1 2 0 1 2 0
We can generalise that appending digit D to some number N shifts the remainder by D%3, in other words we do not need to extract the slice, except for display.
Putting these ideas into practice, and squishing it up just how you like it:
procedure tiny(sequence s) integer l=length(s), r3 for i=1 to l do r3 = 0 for j=i to l do r3 = remainder(r3+s[j]-'0',3) if r3=0 then puts(1,s[i..j]&", ") end if end for end for end procedure tiny("37540")
3. Re: Tight programming exercise, using bad programming practices
- Posted by Spock Jun 18, 2015
- 2724 views
..
We can generalise that appending digit D to some number N shifts the remainder by D%3, in other words we do not need to extract the slice, except for display.
Putting these ideas into practice, and squishing it up just how you like it:
procedure tiny(sequence s) integer l=length(s), r3 for i=1 to l do r3 = 0 for j=i to l do r3 = remainder(r3+s[j]-'0',3) if r3=0 then puts(1,s[i..j]&", ") end if end for end for end procedure tiny("37540")
Pete, '0' is 48, divisible by 3, so that expression could be simplified a little more. In Orac the applicable line would then become:
r3=(r3+s.j)%3
Spock
4. Re: Tight programming exercise, using bad programming practices
- Posted by fizzpopsoft Jun 19, 2015
- 2684 views
Also, by using "for" instead of "while" for the loops, there are less variables to be defined. Nice!
AFAIK, the general algo of attacking the input number as a char string (sequence) with a nested loop,
is better than attempting a pure arithmetic approach. Or any other way?
5. Re: Tight programming exercise, using bad programming practices
- Posted by fizzpopsoft Jun 19, 2015
- 2689 views
The bad practices shown, are the lack of indention, meaningful variable names, comments. Multiple statements on a line. Thats all I hope ;)
Thats the approach I would have needed to use on my first computer, a 1 MHz Sinclair ZX-81 with 768 bytes of ram. Ah, the good old days.. :)
I though the question was fairly evil to ask of a non-programmer, coming up with the nested loop I mean. But I did want to show him the way it should not be done too.
By looking at a task and coming up with the algo, we have to analize what our brains are actually doing and then put that into code.
The improvements suggested are more examples of that.
Not everyone has the talent mentioned above, so regardless of how easy Euphoria might be, we can't all be programmers.
Thanks guys
6. Re: Tight programming exercise, using bad programming practices
- Posted by Spock Jun 21, 2015
- 2587 views
Also, by using "for" instead of "while" for the loops, there are less variables to be defined. Nice!
AFAIK, the general algo of attacking the input number as a char string (sequence) with a nested loop,
is better than attempting a pure arithmetic approach. Or any other way?
There is another way, in this case, since the linear sum of all characters in a multiple of 3 is itself also divisble by 3 (ditto for multiples of 9). Therefore, we can just add chars together, like so:
procedure tiny2(seq s) for i=1 to~s do int n=0 for j=i to~s do n+=s.j if n%3=0 then puts(1,s[i..j]&", ") end if end for end for end procedure
I guess judges would probably disqualify this since it is Orac rather than genuine Euphoria. On the other hand, it is surprisingly readable given that it is the most compact.
Spock
7. Re: Tight programming exercise, using bad programming practices
- Posted by petelomax Jun 21, 2015
- 2607 views
And yet there is also this, which loses points for having no real trickery of any note at all
procedure tiny(sequence s) integer l=length(s),n for i=1 to l do n=0 for j=i to l do n=n*10+s[j]-'0' if remainder(n,3)=0 then printf(1,"%d, ",n) end if end for end for end procedure
Pete
PS I am a bit surprised Orac does not have "for i ~s do"
8. Re: Tight programming exercise, using bad programming practices
- Posted by Spock Jun 21, 2015
- 2579 views
And yet there is also this, which loses points for having no real trickery of any note at all
procedure tiny(sequence s) integer l=length(s),n for i=1 to l do n=0 for j=i to l do n=n*10+s[j]-'0' if remainder(n,3)=0 then printf(1,"%d, ",n) end if end for end for end procedure
Pete
PS I am a bit surprised Orac does not have "for i ~s do"
Dang! It should have, eh? In fact, keywords like do and then are also redundant since the parser knows exactly where the expression ends. This would give us stuff like:
for i ~s for i ~s to 1 -- reverse direction while x if x = CASE1 elsif x = CASE2 proc myproc() func myfunc()
BTW, using eg proc instead of procedure could be done seamlessly [ie, without breaking existing stuff] since the parser can easily know the difference between the keyword proc at the top-level versus a variable called proc at the routine level.
Putting it all together we get:
proc tiny2(seq s) for i ~s int n = 0 for j ~s n += s.j if n%3 = 0 puts(1,s[i to j]&", ") end end end end
But we can't really have stuff like that because that would make Euphoria even easier to use.
Spock
9. Re: Tight programming exercise, using bad programming practices
- Posted by petelomax Jun 21, 2015
- 2562 views
keywords like do and then are also redundant since the parser knows exactly where the expression ends.
I'd be ok if then were changed such that absence meant just one single statement follows, and no end if, otherwise, as now, <block> end if must follow. eg
if a=b puts(1,"a=b\n") if a=b then puts(1,"a=b\n") else puts(1,"a!=b\n") end if
If asked to vote, my personal choice would be if only, and against a similar change to do/for/while, since one-liner loops are pretty rare anyway.
if x = CASE1 elsif x = CASE2
I think that elsif/else should (remain) illegal without a then.
end end end end
I think that is a very bad idea and would argue quite strongly against dropping the end qualifier, in my opinion it is one of Eu's greatest strengths, and has saved me from myself countless times.
But we can't really have stuff like that because that would make Euphoria even easier to use.
Ha ha. Joking aside, for me the whole ease of use point is what it does, in terms of friendly error messages, with whatever you have had to type, whether terse or verbose, rather than C++'s idea of playing at mini Dr Evil: "There is a bug <tee-hee>, somewhere in your code".
Pete