I can't figure this one out

May 20, 2008
9,144
58
Syracuse, NY, USA
Here (below) is a BTM to answer a math question from the folklore (question at the end). It doesn't work because I can't get past the marked like. Whenever I reach it (first time when count == 1601) I get
Code:
TCC: V:\number.btm [18]  Syntax error "10*n+g"
At that time, BDEBUGGER tells me n = 123252 and g = 1 (which are OK).

News flash! ... It works if, in that line only, I use "%n" instead of "n" (and it arrives at the right answer).

I don't get it. This must be a very obscure bug (or I'm missing something utterly obvious).

Code:
set count=0
do a=1 to 9 by 2
   do b=2 to 8 by 2
       do c=1 to 9 by 2
           do d=2 to 8 by 2
               do f=2 to 8 by 2
                   do g=1 to 9 by 2
                       do h=2 to 8 by 2
                           do i=1 to 9 by 2
                               set /a count+=1
                               set bcontinue=0
                               set /a n=100*a+10*b+c
                               if %@eval[n MOD 3] NE 0 iterate
                               set /a n=10*n+d
                               if %@eval[n MOD 4] NE 0 iterate
                               set /a n=100*n+50+f
                               if %@eval[n MOD 6] NE 0 iterate
                               set /a n=10*n+g & REM <===================== this line
                               if %@eval[n MOD 7] NE 0 iterate
                               set /a n=10*n+h
                               if %@eval[n MOD 8] NE 0 iterate
                               set /a n=10*n+i
                               if %@eval[n MOD 9] NE 0 iterate
                               do z=1 to 9
                                   if %@index[%n,%z] == -1 (set bcontinue=1 & leave)
                               enddo
                               if %bcontinue == 1 iterate
                               echo %n
                           enddo
                       enddo
                   enddo
               enddo
           enddo
       enddo
   enddo
enddo
The question: Find a 9-digit number which uses each of 1, 2, ..., 9 exactly once, and has the property that, for i=1 to 9, the number comprising its left-hand i digits is divisible by i. The answer is unique.
 
May 20, 2008
9,144
58
Syracuse, NY, USA
If I comment the line before the troublesome one, I get no errors (and no answer).

If I replace the line before
Code:
if %@eval[n MOD 6] NE 0 iterate
with
Code:
if %@eval[6*(n\6)] != %n iterate
(an equivalent test) I avoid the error and get the right answer.
 
May 20, 2008
9,144
58
Syracuse, NY, USA
Boiled down: It's got something to do with the letter 'g'. Compare the last two of these:
Code:
v:\> set n=0

v:\> set g=0

v:\> set z=0

v:\> set /a n=z
0

v:\> set /a n=g
TCC: Syntax error "g"
I don't know if it's relevant, but MAPM_SET.C has a buggy routine for validating a string (as a number). More on that if desired.
 

rconn

Administrator
Staff member
May 14, 2008
10,885
97
Some single characters have a special meaning within the expression analyzer.

I am removing all of the (undocumented and unsupported) functionality in SET /A that isn't supported in CMD. (I.e., floating point, functions, hex numbers, binary numbers, rotates, etc.) in the next build, so if you're using strictly CMD syntax these issues won't arise any longer. If you're not using CMD syntax, you shouldn't be using SET /A.
 
May 20, 2008
9,144
58
Syracuse, NY, USA
Some single characters have a special meaning within the expression analyzer.

I am removing all of the (undocumented and unsupported) functionality in SET /A that isn't supported in CMD. (I.e., floating point, functions, hex numbers, binary numbers, rotates, etc.) in the next build, so if you're using strictly CMD syntax these issues won't arise any longer. If you're not using CMD syntax, you shouldn't be using SET /A.
Hmmm! It's been as it is for ... how many years? I thought you didn't like breaking people's batch files. I doubt I'll be the only one.
 

rconn

Administrator
Staff member
May 14, 2008
10,885
97
Hmmm! It's been as it is for ... how many years? I thought you didn't like breaking people's batch files. I doubt I'll be the only one.
And I've told you for the last umpteen years not to do that.

I have to make the change because the current (undocumented + unsupported + strongly discouraged) behavior is breaking CMD compatibility.
 
May 20, 2008
9,144
58
Syracuse, NY, USA
As a matter of fact, the line in question,
Code:
set /a n=10*n+g
conforms to the the rules mentioned in CMD's "SET /?" and it works in CMD.
Code:
C:\Users\vefatica> ver

Microsoft Windows [Version 6.1.7601]

C:\Users\vefatica> set n=2

C:\Users\vefatica> set g=5

C:\Users\vefatica> set /a n=10*n+g
25
 
May 20, 2008
9,144
58
Syracuse, NY, USA
Some single characters have a special meaning within the expression analyzer.

I am removing all of the (undocumented and unsupported) functionality in SET /A that isn't supported in CMD. (I.e., floating point, functions, hex numbers, binary numbers, rotates, etc.) in the next build, so if you're using strictly CMD syntax these issues won't arise any longer. If you're not using CMD syntax, you shouldn't be using SET /A.
Will that remove the need for characters with special meaning? The 'g' is the problem, even with @EVAL.
Code:
v:\> set n=2

v:\> set g=5

v:\> set n=%@eval[10*n+g]
TCC: Syntax error "10*n+g"
 

rconn

Administrator
Staff member
May 14, 2008
10,885
97
As a matter of fact, the line in question,
Code:
set /a n=10*n+g
conforms to the the rules mentioned in CMD's "SET /?" and it works in CMD.
Code:
C:\Users\vefatica> ver

Microsoft Windows [Version 6.1.7601]

C:\Users\vefatica> set n=2

C:\Users\vefatica> set g=5

C:\Users\vefatica> set /a n=10*n+g
25
And it works in 21.01.50. But in order to do that, I had to remove the undocumented behavior (functions, floating point, etc.).
 
May 20, 2008
9,144
58
Syracuse, NY, USA
And it works in 21.01.50. But in order to do that, I had to remove the undocumented behavior (functions, floating point, etc.).
Does any of this have to do with m_apm_set_string() not working very well? For example "a","b", and"c" cause a "non-digit" complaint from MAPM; "d" causes an access violation; "g" turns into the number 3, "gg" into 93.
 
May 20, 2008
9,144
58
Syracuse, NY, USA
FWIW ...
The original version of the BTM:
Code:
v:\> timer number.btm
Timer 1 on: 15:55:46
381654729
Timer 1 off: 15:57:02  Elapsed: 0:01:16.63
A tweaked version:
Code:
v:\> timer number.btm
Timer 1 on: 17:09:16
381654729
Timer 1 off: 17:09:27  Elapsed: 0:00:11.59
The speed increase was about half due to BTM tweaks (notably, keep it short and unset as much as you can) and about half due to the math observation that the 4th and 8th digits had to be 2 or 6. Here's the tweaked version.
Code:
setlocal
unalias *
unset *
do a=1 to 9 by 2
do b=2 to 8 by 2
do c=1 to 9 by 2
do d=2 to 6 by 4
do f=2 to 8 by 2
do g=1 to 9 by 2
do h=2 to 6 by 4
do i=1 to 9 by 2
set /a n=100*a+10*b+c & if %@eval[n MOD 3] NE 0 iterate
set /a n=10*n+d & if %@eval[n MOD 4] NE 0 iterate
set /a n=100*n+50+f & if %@eval[n MOD 6] NE 0 iterate
set /a n=(10*n+g) & if %@eval[n MOD 7] NE 0 iterate
set /a n=10*n+h & if %@eval[n MOD 8] NE 0 iterate
set /a n=10*n+i & if %@eval[n MOD 9] NE 0 iterate
do z=1 to 9 (if %@index[%n,%z] == -1 (set x=1 & leave))
if defined x (unset x & iterate)
echo %n & quit
enddo
enddo
enddo
enddo
enddo
enddo
enddo
enddo
 
May 20, 2008
9,144
58
Syracuse, NY, USA
Taking further advantage of the fact that the 4th and 8th digits must (one of) 2 and 6,
Code:
v:\> timer number.btm
Timer 1 on: 21:45:57
381654729
Timer 1 off: 21:46:02  Elapsed: 0:00:05.47

v:\> type number.btm
setlocal
unalias *
unset *
do a=1 to 9 by 2
do b=2 to 8 by 2
do c=1 to 9 by 2
do d=2 to 6 by 4
set h=%@if[%d == 2,6,2]
do f=2 to 8 by 2
do g=1 to 9 by 2
do i=1 to 9 by 2
set /a n=100*a+10*b+c & if %@eval[n MOD 3] NE 0 iterate
set /a n=10*n+d & if %@eval[n MOD 4] NE 0 iterate
set /a n=100*n+50+f & if %@eval[n MOD 6] NE 0 iterate
set /a n=(10*n+g) & if %@eval[n MOD 7] NE 0 iterate
set /a n=10*n+h & if %@eval[n MOD 8] NE 0 iterate
set /a n=10*n+i & if %@eval[n MOD 9] NE 0 iterate
do z=1 to 9 (if %@index[%n,%z] == -1 (set x=1 & leave))
if defined x (unset x & iterate)
echo %n & quit
enddo
enddo
enddo
enddo
enddo
enddo
enddo