I can't figure this one out

#1
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.
 
#2
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.
 
#4
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,506
94
#6
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.
 
#7
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,506
94
#8
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.
 
#9
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
 
#10
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,506
94
#12
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.).
 
#13
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.
 
#14
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
 
#16
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