[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

【出题】批处理输出n阶幻方

所谓n阶幻方:1-n^2个数排为n行n列,横、竖、对角线相加和相同。
  输入:幻方阶数n (暂限制为奇数阶)
  输出:n行n列的方阵,横、竖、对角线相加和相同。
  举例:5阶幻方,横、竖、对角线相加和为65
17 24  1  8 15
23  5  7 14 16
4  6 13 20 22
10 12 19 21  3
11 18 25  2  9

回复 37楼 的帖子

把setlocal enabledelayedexpansion放在for语句里面是为了防止读取某些含有叹号!字符串时,丢失叹号!字符。

而你的这个算幻方的题,可能不涉及到叹号!字符串的处理。所以可以把setlocal enabledelayedexpansion放在for语句外面防止超过最大递归层。

但当你处理一些含有叹号!字符串时,应该注意把setlocal enabledelayedexpansion放在for语句内部,防止丢失。

这就叫 “随机应变”,就是看情况选择setlocal enabledelayedexpansion的位置。
(*^_^*)

TOP

回复 36楼 的帖子

那个帖子我看了,上面说最好把变量延迟扩展申明放在for结构内,哪里需要哪里申明,然后再结束,那我的问题不就没办法解决了么?我试过了,在for里申明然后在结构结束之前用endlocal结束,结果还是会出现那个恼人的错误提示。但是我照33楼兄弟的说法把申明放到for结构之前,问题就没有了。到底哪个是对的?如果要放在for里面的话,如何把我的问题解决?
Still with wax

TOP

回复 35楼 的帖子

确实应该好好看看,也许你会发现不把变量延迟扩展放在for里面有时可能带来更多的问题^_^
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 33楼 的帖子

呵呵,就要这种效果,一句话就解决,我把变量延迟放到外面就不会提示那个错误了。再去好好看看这个问题的描述,多谢啦!
Still with wax

TOP

回复 31楼 的帖子

“已经达到最大的setlocal递归层”的问题,请参考:
http://bbs.bathome.net/thread-1224-1-3.html
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

变量延迟不要放在for里面

TOP

晕菜啊,这么久也没人来指点一下啊,再等~
Still with wax

TOP

凑热闹

好早之前看到这个帖子了,在这个帖子还没有回复的时候就开始研究写了代码,可是错误不少,后来因为工作的事就一直没时间去斟酌。现在有时间了,仔细看了下,终于改出来了,本来挺高兴的,结果上来一看,前辈们早就把代码反复推敲了N久了,而且问题的本质已经从对症下药给出合理的解决代码上升倒了代码效率高下的研究,这是本人不敢企及的。本来不打算把代码贴上来了,可是本人后来输入较大点的数字的时候,又出现一个问题,就是“已经达到最大的setlocal递归层”但是似乎幻方的生成还是没有影响,数字也都对,我不太明白这个错误怎么长生的。老调重弹,麻烦前辈们给解释下,不胜感激!
我写的代码如下:
  1. @echo off
  2. :start
  3. set /p n=Please input your odd integer:
  4. set /a p=n%%2
  5. if %p% equ 0 echo Input error!&&goto start
  6. set /a i=%n%
  7. set /a t=(%n%+1)/2
  8. set /a a%t%_%n%=1,temp=1,m=n-1,p=n
  9. :repeat
  10. set /a p-=1
  11. if %p% lss 0 goto array
  12. for /l %%a in (1 1 %m%) do (
  13.    setlocal enabledelayedexpansion
  14.    if !t! gtr %n% set /a t=1
  15.    if !i! gtr %n% set /a i=1
  16.    set /a s=!t!+1,q=!i!+1
  17.    if !s! gtr %n% set /a s=1
  18.    if !q! gtr %n% set /a q=1
  19.    set /a a!s!_!q!=a!t!_!i!+1,t+=1,i+=1
  20.    set /a temp+=1
  21.    if !temp! equ %n% (
  22.          set /a temp=1,tmp=a!s!_!q!,q-=1,i-=1
  23.          if !q! equ 0 set /a q=n
  24.          set /a a!s!_!q!=tmp+1
  25.          goto repeat
  26. )   
  27. )
  28. pause
  29. :array
  30. echo Now behold the powerful Magic Sqaure^^!:
  31. set /a a!t!_!n!=1
  32. for /l %%c in (!n! -1 1) do (
  33.    for /l %%d in (1 1 !n!) do (
  34.               set /a result=a%%d_%%c
  35.               set /p=!result!<nul      
  36. )
  37. echo.
  38. )
  39. pause>nul
复制代码
如上,输入7以上的奇数就会出现那个问题,没弄明白,只好请教诸位了。
Still with wax

TOP

按照兄的建议修改了下,感觉效率还有待提高。批代码中大量操作都用于矩阵的赋值与运算,而高级语言中数组则作为内嵌类型,而MATLAB更是以矩阵作为基本的操作单元,所以对矩阵进行线性运算耗费时间很低,可能这也就是其效率高的原因吧。
    MATLAB中有很多经典算法,并且许多用于数值分析的算法都是世界一流的算法,效率自然很高,许多的源代码都是可以自己修改的,也很值得学习借鉴。我现在也就只能看懂整个程序的流程,至于为什么如此构造可以实现(以幻方为例)我还想不明白,这确实需要很强的数学背景了!

TOP

想通过代码来了解算法太难了,大致看了下兄的代码流程,只发现一处影响代码效率的地方。
批处理的运行效率,个人认为 set 或 set /a 并不会太影响,关键是看代码的设计,for的循环次数尤其是嵌套循环,再就是call若在for循环中有call则一定会使效率大打折扣。
建议改进的地方:
:exchange 标签下
call set _%%i%%j=%%_!i!%%j%%
改为 for %%a in (!i!) do set _%%i%%j=!_%%a%%j!
技术问题请到论坛发帖求助!

TOP

下午偶然从MATLAB上找到了构造幻方的源代码,是用MATLAB程序设计语言实现的(基于C语言设计),可以生成阶数不限的幻方。下午把此算法用批处理实现了。下面附上批版代码以及magic(n)函数源代码。
  1. @echo off
  2. :begin
  3. setlocal enabledelayedexpansion
  4. set rank=
  5. echo.&set /p "rank=请输入幻方阶数:"
  6. set /a remainder=rank%%2
  7. if !remainder! equ 1 (
  8.     call :odd !rank!
  9. ) else (
  10.      set /a remainder=rank%%4
  11.      if !remainder! equ 0 (
  12.         call :even_4
  13.      ) else call :even_2
  14.    )
  15. rem --------------奇数阶幻方------------------
  16. :odd
  17. set rank=%1
  18. call :create
  19. for /l %%i in (1 1 !rank!) do (
  20.      for /l %%j in (1 1 !rank!) do (
  21.          set /a $%%i%%j="(.%%i%%j+.%%j%%i-(rank+3)/2+rank)%%rank"
  22.          set /a #%%i%%j="(.%%i%%j+.%%j%%i*2-2+rank)%%rank"
  23.          set /a _%%i%%j="rank*$%%i%%j+#%%i%%j+1"
  24.      )
  25.   )
  26. if not "%~2" equ "" goto :eof
  27. call :output
  28. endlocal&goto :begin
  29. rem -------------偶数阶幻方(4整除)---------------
  30. :even_4
  31. call :create
  32. set num=0
  33. for /l %%i in (1 1 !rank!) do (
  34.      for /l %%j in (1 1 !rank!) do (
  35.          set /a "a=(.%%i%%j%%4)/2,b=(.%%j%%i%%4)/2"
  36.          if !a! equ !b! ( set "_%%i%%j=1" ) else set "_%%i%%j=0"
  37.          set /a "num+=1,n=rank*rank+1"
  38.          set /a #%%i%%j=!num!
  39.          if !_%%i%%j! equ 1 (set /a _%%i%%j=n-#%%i%%j) else set _%%i%%j=!#%%i%%j!
  40.      )
  41. )
  42. call :output
  43. endlocal&goto :begin
  44. rem --------------偶数阶幻方(2整除)--------------
  45. :even_2
  46. set /a p=rank/2,q=rank,p1=p+1
  47. call :odd !p! OK
  48. set rank=!q!
  49. call :rearrange 1 !p! !p1! !rank! 2
  50. call :rearrange !p1! !rank! 1 !p! 3
  51. call :rearrange !p1! !rank! !p1! !rank! 1
  52. call :transpos !p!
  53. if !rank! equ 2 (
  54.    call :output
  55.    endlocal&goto :begin
  56. )
  57. for /l %%i in (1 1 !p!) do set "var_i=!var_i! %%i"
  58. set /a k=(rank-2)/4,m=rank-k+2
  59. for /l %%i in (1 1 !k!) do set "var_j=!var_j! %%i"
  60. for /l %%i in (!m! 1 !rank!) do set "var_j=!var_j! %%i"
  61. call :exchange "!var_i!" "!var_j!"
  62. set /a i=k+1
  63. set "j=1 !i!"
  64. call :exchange "!i!" "!j!"
  65. call :output
  66. set i=
  67. set j=
  68. set var_i=
  69. set var_j=
  70. endlocal&goto :begin
  71. rem -------------以下为子函数-----------------
  72. :create
  73. set /a rank_2=rank*rank,i=1,j=1
  74. for /l %%i in (1 1 !rank_2!) do (
  75.        set .!i!!j!=!j!
  76.        set /a j+=1
  77.        if !j! gtr !rank! set j=1&set /a i+=1
  78. )
  79. goto :eof
  80. :output
  81.   call :append !rank!
  82.   for /l %%i in (1 1 !rank!) do (
  83.      for /l %%j in (1 1 !rank!) do set result=!result! !_%%i%%j:~-3!
  84.      echo.!result!&set result=
  85.   )
  86.   goto :eof
  87. :rearrange
  88. set /a p2=%5*p*p,i=1,j=1
  89. for /l %%i in (%1 1 %2) do (
  90.      for /l %%j in (%3 1 %4) do (
  91.          set /a _%%i%%j=_!j!!i!+p2
  92.          set /a j+=1
  93.      )
  94.      set /a "i+=1,j=1"
  95. )
  96. goto :eof
  97. :exchange
  98. for %%i in (%~1) do (
  99.      for %%j in (%~2) do (
  100.          set /a i=%%i+p
  101.          set tmp=!_%%i%%j!
  102.          call set _%%i%%j=%%_!i!%%j%%
  103.          set _!i!%%j=!tmp!
  104.      )
  105. )
  106. goto :eof
  107. :transpos
  108. for /l %%i in (1 1 %1) do (
  109.      for /l %%j in (%%i 1 %1) do (
  110.          if not %%i equ %%j (
  111.             set tmp=!_%%i%%j!
  112.             set _%%i%%j=!_%%j%%i!
  113.             set _%%j%%i=!tmp!
  114.          )
  115.      )
  116. )
  117. goto :eof
  118. :append
  119.   for /l %%i in (1 1 %1) do (
  120.      for /l %%j in (1 1 %1) do (
  121.          set "_%%i%%j=   !_%%i%%j!"
  122.      )
  123.   )
  124.   goto :eof
复制代码
函数magic(n);
function M = magic(n)
%MAGIC  Magic square.
%   MAGIC(N) is an N-by-N matrix constructed from the integers
%   1 through N^2 with equal row, column, and diagonal sums.
%   Produces valid magic squares for all N > 0 except N = 2.

%   Copyright 1984-2002 The MathWorks, Inc.
%   $Revision: 5.15 $  $Date: 2002/04/15 03:44:23 $

% Historically, MATLAB's magic was a built-in function.
% This M-file uses a new algorithm to generate the same matrices.

n = floor(real(double(n(1))));

% Odd order.
if mod(n,2) == 1
   [J,I] = meshgrid(1:n);
   A = mod(I+J-(n+3)/2,n);
   B = mod(I+2*J-2,n);
   M = n*A + B + 1;

% Doubly even order.
elseif mod(n,4) == 0
   [J,I] = meshgrid(1:n);
   K = fix(mod(I,4)/2) == fix(mod(J,4)/2);
   M = reshape(1:n*n,n,n)';
   M(K) = n*n+1 - M(K);

% Singly even order.
else
   p = n/2;
   M = magic(p);
   M = [M M+2*p^2; M+3*p^2 M+p^2];
   if n == 2, return, end
   i = (1:p)';
   k = (n-2)/4;
   j = [1:k (n-k+2):n];
   M([i; i+p],j) = M([i+p; i],j);
   i = k+1;
   j = [1 i];
   M([i; i+p],j) = M([i+p; i],j);
end

分三种情况,奇数、偶数、双偶数。MATLAB源代码中调用了一些函数,可以在帮助文档中找到。
附:
    在MATLAB软件环境下用命令调用magic(n),效率很高,上千阶的幻方也只需要2-3秒;可用批实现的代码效率却不尽如人意,比上面几楼各位的代码还要低些,可能是大量的变量赋值运算影响了效率吧;大家再来优化下代码,看哪里还有提升的空间。

TOP

嗯,我承认我是迟到了...而且还不是batch的...
是python的:
  1. #09/4/4/12
  2. def make_list(num):
  3.     n,k,b,c = num,0,num/2,num**2
  4.     listx = []
  5.     for x in xrange(n):
  6.         listx.append([])
  7.         for _x in xrange(n):
  8.             listx[x].append(False)
  9.     for _x in xrange(c):
  10.         if((_x+1)==1):
  11.             listx[k] = 1
  12.         elif((_x+1)%n==1):
  13.             k = k+1
  14.             if(k>n-1):
  15.                 k = k-n
  16.             listx[k] = _x+1
  17.         else:
  18.             k = k+2
  19.             b = b+1
  20.             if(b>n-1):
  21.                 b = 0
  22.             if(k>n-1):
  23.                 k = k-n
  24.             listx[k] = _x+1
  25.     for y in xrange(n):
  26.             print(listx[y])
  27. def start():
  28.     print("Input a number:")
  29.     x = input()
  30.     if(x%2==0):
  31.         print("Wrong.")
  32.     else:
  33.         make_list(x)
  34. if __name__ == "__main__":
  35.      start()
复制代码

[ 本帖最后由 xxx 于 2009-4-12 14:05 编辑 ]

TOP

真是厉害,呀 向大家学习

TOP

凑热闹 马步的
修改前面的set ".!h!-!m!=1"这句放在FOR里面
  1. @echo off
  2. :start
  3. setlocal enabledelayedexpansion
  4. echo.&set /p n= 请输入一个奇数 &cls
  5. set /a m=n/2+1,c=n*n,he=(n*n+1)*n/2
  6. echo  !n! 阶幻方各行,列以及对角线相加的和为: %he%&echo.
  7. for /l %%i in (1 1 !c!) do (
  8.    set/a i=%%i%%n
  9.    if !i! equ 1 (set/a h=h%%n+1) else set/a h=h%%n+2,m=m%%n+1
  10.    if !h! gtr !n! set h=1
  11.       set ".!h!-!m!=%%i"
  12. )
  13. for %%i in (0 1 10) do if not "!c:~%%i,1!"=="" set /a j=%%i+2&set "k=!k! "
  14. for /l %%a in (1 1 !n!) do (
  15.    set "var="
  16.    for /l %%b in (1 1 !n!) do (
  17.       set "str=!k!!.%%a-%%b!"
  18.       set "var=!var! !str:~-%j%!"
  19.     )
  20.     echo.!var:~1!
  21. )
  22. pause
  23. endlocal&goto start
复制代码

[ 本帖最后由 terse 于 2009-4-6 11:07 编辑 ]
1

评分人数

    • more: 厉害PB + 12 技术 + 1

TOP

返回列表