可视化尼科马修斯定理


35

Nichomachus定理将总和的平方与立方体总和联系起来:

尼科马丘斯定理

并具有漂亮的几何可视化效果:

可视化

挑战:在ascii中创建此可视化的2d部分。

您将需要确保图保留所有视觉分界。这是最简单的用四种“颜色”进行的操作,尽管只用三种就可以实现(有关详细信息,请参见下面的最后一个示例)。对于四种颜色,您可以使用两种颜色来区分“条”中的区域(即,组成一个立方体的不同部分),而使用两种颜色来区分相邻的条带。如果您愿意,也可以使用四种以上的颜色。如果有任何令人困惑的地方,下面的示例输出应予以澄清。

输入输出

输入是一个大于0的整数。输出是一个与以下示例类似的ascii网格,对应于上图中该输入数字的扁平网格。开头和结尾的空格都可以。

这是标准规则的代码高尔夫。

样本输出

N = 1

#

N = 2

#oo   
o@@   
o@@   

N = 3

#oo+++
o@@+++
o@@+++
+++###
+++###
+++###

N = 4

#oo+++oooo
o@@+++oooo
o@@+++@@@@
+++###@@@@
+++###@@@@
+++###@@@@
oo@@@@oooo
oo@@@@oooo
oo@@@@oooo
oo@@@@oooo

N = 5

#oo+++oooo+++++
o@@+++oooo+++++
o@@+++@@@@+++++
+++###@@@@+++++
+++###@@@@+++++
+++###@@@@#####
oo@@@@oooo#####
oo@@@@oooo#####
oo@@@@oooo#####
oo@@@@oooo#####
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++

由于@ BruceForte,N = 4的三种颜色版本:

#oo+++oooo
o##+++oooo
o##+++####
+++ooo####
+++ooo####
+++ooo####
oo####++++
oo####++++
oo####++++
oo####++++

6
四色定理:D
Leaky Nun

1
您能否将N = 5的输出相加?
Uriel

1
@Uriel完成。看到我的编辑。
约拿(Jonah)

谢谢!另外,能否仅在N = 4的外部条中切换@和os?还是输出必须用其他字符集严格替换这些文本?
Uriel

@Uriel切换很好。重要的是相邻的颜色不会冲突,因此图案是可见的。
约拿(Jonah)

Answers:


17

MATL30 28 27字节

t:P"@:s:@/Xk&+@+8MPt&(]30+c

在线尝试!

奖励功能:

  • 对于26个字节,以下修改后的版本将产生图形输出

    t:P"@:s:@/Xk&+@+8MPt&(]1YG
    

    MATL在线上尝试一下

  • 该图像乞求某种颜色,它仅花费7个字节:

    t:P"@:s:@/Xk&+@+8MPt&(]1YG59Y02ZG
    

    MATL在线上尝试一下

  • 或使用更长的版本(37字节)来查看字符矩阵是如何逐步构建的

    t:P"@:s:@/Xk&+@+8MPt&(t30+cD9&Xx]30+c
    

    MATL在线上尝试一下

输出示例

输入为8,下面显示了基本版本,图形输出和彩色图形输出。

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

说明

一般程序

数字矩阵是从外层到内层N逐步构建的,N输入在哪里。每个步骤都会覆盖前一个矩阵的内部(左上)部分。最后,将获得的矩阵中的数字更改为字符。

对于输入4,第一个矩阵是

10 10  9  9  9  9  8  8  8  8
10 10  9  9  9  9  8  8  8  8
 9  9  8  8  8  8  7  7  7  7
 9  9  8  8  8  8  7  7  7  7
 9  9  8  8  8  8  7  7  7  7
 9  9  8  8  8  8  7  7  7  7
 8  8  7  7  7  7  6  6  6  6
 8  8  7  7  7  7  6  6  6  6
 8  8  7  7  7  7  6  6  6  6
 8  8  7  7  7  7  6  6  6  6

第二步,矩阵

7 7 7 6 6 6
7 7 7 6 6 6
7 7 7 6 6 6
6 6 6 5 5 5
6 6 6 5 5 5
6 6 6 5 5 5

被覆盖到后者的上半部分。然后用同样的方法

6 5 5
5 4 4
5 4 4

最后是

3

所得矩阵为

3 5 5 6 6 6 8 8 8 8
5 4 4 6 6 6 8 8 8 8
5 4 4 6 6 6 7 7 7 7
6 6 6 5 5 5 7 7 7 7
6 6 6 5 5 5 7 7 7 7
6 6 6 5 5 5 7 7 7 7
8 8 7 7 7 7 6 6 6 6
8 8 7 7 7 7 6 6 6 6
8 8 7 7 7 7 6 6 6 6
8 8 7 7 7 7 6 6 6 6

最后,30将其添加到每个条目,并将生成的数字解释为代码点并转换为字符(因此从开头33,与相对应!)。

中间矩阵的构建

对于输入N,请考虑减小kN到的值1。对于每个k,生成一个从1到的整数向量k*(k+1),然后将每个条目除以k并四舍五入。例如,k=4为此给出(k除最后一个块外,所有块均具有大小):

1 1 1 1 2 2 2 2 3 3

k=3结果将是(所有块都具有size k):

1 1 1 2 2 2

此向量通过广播逐元素地添加到其自身的转置副本中;然后k添加到每个条目中。为此k=4

6  6  6  6  7  7  7  7  8  8
6  6  6  6  7  7  7  7  8  8
6  6  6  6  7  7  7  7  8  8
6  6  6  6  7  7  7  7  8  8
7  7  7  7  8  8  8  8  9  9
7  7  7  7  8  8  8  8  9  9
7  7  7  7  8  8  8  8  9  9
7  7  7  7  8  8  8  8  9  9
8  8  8  8  9  9  9  9 10 10
8  8  8  8  9  9  9  9 10 10

这是上面显示的中间矩阵之一,只是水平和垂直翻转。因此,剩下的就是翻转该矩阵并将其写入到目前为止的“累加”矩阵的左上角,并为第一步(k=N)初始化为一个空矩阵。

t       % Implicitly input N. Duplicate. The first copy of N serves as the
        % initial state of the "accumulated" matrix (size 1×1). This will be 
        % extended to size N*(N+1)/2 × N*(N+1)/2 in the first iteration
 :P     % Range and flip: generates vector [N, N-1, ..., 1]
"       % For each k in that vector
  @:    %   Push vector [1, 2, ..., k]
  s     %   Sum of this vector. This gives 1+2+···+k = k*(k+1)/2
  :     %   Range: gives vector [1, 2, ..., k*(k+1)/2]
  @/    %   Divide each entry by k
  Xk    %   Round up
  &+    %   Add vector to itself transposed, element-wise with broadcast. Gives
        %   a square matrix of size k*(k+1)/2 × k*(k+1)/2
  @+    %   Add k to each entry of the this matrix. This is the flipped
        %   intermediate matrix
  8M    %   Push vector [1, 2, ..., k*(k+1)/2] again
  Pt    %   Flip and duplicate. The two resulting, equal vectors are the row and
        %   column indices where the generated matrix will be written. Note that
        %   flipping the indices has the same effect as flipping the matrix
        %   horizontally and vertically (but it's shorter)
  &(    %   Write the (flipped) intermediate matrix into the upper-left
        %   corner of the accumulated matrix, as given by the two (flipped)
        %   index vectors 
]       % End
30+     % Add 30 to each entry of the final accumulated matrix
c       % Convert to char. Implicitly display

我一点都不了解MATL,但是您能通过采用mod10而不是加30并转换为字符来保存任何字节吗?
user2390246

甚至是mod4 ...
user2390246

@ user2390246您的意思是将它们保留为一位数字,并避免转换为char吗?那是行不通的,因为数字矩阵将在数字之间用空格打印。但是还是要感谢这个主意:-)
路易斯·门多

很公平。n> 226会发生什么?那不会超出有效字符范围吗?(毫不奇怪,在TIO上超时,所以我无法检查)
user2390246

@ user2390246是的,对于高输入数字,它出在外面。而且,如果我们考虑ASCII字符,则最大代码点为127,因此它甚至更早地出局。但是正如您所注意到的,它在此之前耗尽了内存(生成的char矩阵太大)。无论如何,通常只允许由于内存或数据类型限制而达到给定的输入大小
Luis Mendo

7

Python 2中187个 178 164 162 152字节

-8字节归功于Mr.Xcoder
-1字节归功于Stephen
-10字节归功于Jonathan Frech

g=lambda y:y>1and[l+y*f(y,i)for i,l in enumerate(g(y-1))]+y*[''.join(f(y,i)for i in range(y*-~y/2))]or['#']
f=lambda y,i:'0@+#'[(y*~-y/2%y+i)/y%2+y%2*2]

在线尝试!


当您回家时,为179个字节
Xcoder先生17年

@ Mr.Xcoder 178个字节
Stephen

1
递归使用时是否允许不包含lambda函数的名称字节数,即在其余代码中使用其名称?
乔纳森·弗雷希

sum(range(y))%y->y*~-y/2%y
乔纳森·弗雷奇

@JonathanFrech是的,当它是递归的时,它必须在那里。

7

木炭50 46字节

F⮌…·¹N«≔⊘×ι⊕ιθF⊕⊘ι«F§#+@⁺ικ«UO⁻θ×ικθλUOθ⁻θ×ικλ

在线尝试!链接是详细版本的代码。先前的50字节版本及其说明:在线尝试!

F⮌…·¹N«≔÷×ι⁺¹ι²θF⁺¹÷鲫F§#+@⁺ικ«UO⁻θ×ικθλUOθ⁻θ×ικλ

F     «     Loop over
  …·¹       Inclusive range from 1 to
     N      Input as a number
 ⮌          Reversed

   ι⁺¹        Add 1 to current index
  ×   ι       Multiply by current index
 ÷     ²      Divide by 2
≔       θ     Assign to q

F     «      Loop over
             Implicit range from 0 to
   ÷ι²       Half the current index
 ⁺¹          Plus 1

F       «    Loop over
  #+@        Literal string
 §           Circularly indexed by
     ⁺ικ     Sum of outer and inner index

    ×ικ     Multiply outer and inner index
  ⁻θ        Subtract from q
UO     θλ   Draw an oblong (q-ik, q) using that character

UOθ⁻θ×ικλ   Draw an oblong (q, q-ik) using that character

注意:我遍历字符而不是尝试直接将字符分配给该字符,l因为您不能直接将索引字符串的结果分配给变量,因为它是Charcoal中的歧义结构。幸运的是字节数是相同的。


从技术上讲,您可以使用ASCII变量,因为其参数顺序是相反的(请注意,它需要操作员才能访问,因此它的操作性仍然较低)
仅ASCII的2009年

5

C(GCC) 135 128 120个字节

f(n,m,i,x,y,k){for(m=n*-~n/2,i=m*m;i--;printf("\n%d"+!!(~i%m),(x/k+y/k+k)%3))for(x=i%m,y=i/m,k=n;x>=k&y>=k;x-=k--)y-=k;}

在线尝试!

仅使用三种颜色。

从概念上讲,可在旋转180度的网格上工作:

000111
000111
000111
111220
111220
111001

并根据以下公式计算颜色:

c(x,y,n) = c(x-n,y-n,n-1)                   if x >= n and y >= n
         = (x div n + y div n + n) mod 3    otherwise


@JonathanFrech这不是有效的C,并且与中断gcc -O2
nwellnhof

很公平; 由于模数为三(g(i%m,i/m,n)%3),第二个代码是否可能仅适用于三种颜色?
乔纳森·弗雷希

建议x/k&&y/k不要使用x>=k&y>=k
ceilingcat '18

2

[R 131个 126 123字节

@Giuseppe节省了3个字节

function(n){l=w=sum(1:n)
m=matrix(,l,l)
for(i in n:1){m[l:1,l:1]=outer(x<-(1:l-1)%/%i,x,`+`)+i
l=l-i}
write(m%%4,"",w,,"")}

在线尝试!

这使用与@LuisMendo的MATL答案相同的算法。唯一的区别是,矩阵不输出为字符,而是输出所有值mod4以确保每个元素都是单个ascii字符。


1
123字节!我将for循环恢复为-1个字节:)
Giuseppe

1

Python 2中176个 175字节

n=input()
R,J=range,''.join;r=[]
for i in R(n+1):
 S=sum(R(i));c='AxBo'[i%2::2]
 for j in R(S):r[~j]+=c[j/i%2]*i
 r+=[J(c[-j/i%2]for j in R(S+i,0,-1))]*i
for l in r:print J(l)

在线尝试!


如果定义J="".join;(+10字节)并将两个"".join(-2 * 7 = -14字节)都替换为J(+2字节),则可以保存一个字节(因为在print+1字节之后必须有一个额外的空格) 。
乔纳森·弗雷希
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.