Visualisasikan Teorema Nicomachus

35

Teorema Nichomachus mengaitkan kuadrat dari jumlah ke jumlah kubus:

Teorema Nichomachus

dan memiliki visualisasi geometris yang indah:

Visualisasi

Tantangan: Buat bagian 2d dari visualisasi ini di ascii.

Anda perlu memastikan bahwa semua demarkasi visual ditegakkan oleh diagram Anda. Ini paling sederhana untuk dilakukan dengan empat "warna," meskipun mungkin dicapai hanya dengan tiga (lihat contoh terakhir di bawah ini untuk mengetahui bagaimana). Dengan empat warna, Anda menggunakan dua untuk membedakan wilayah dalam "strip" (yaitu, bagian berbeda yang membentuk kubus tunggal), dan dua untuk membedakan antara strip yang berdekatan. Anda juga dapat menggunakan lebih dari empat warna jika suka. Jika salah satu dari ini membingungkan, contoh hasil di bawah ini harus menjelaskan.

Input output

Input adalah bilangan bulat tunggal yang lebih besar dari 0. Output adalah kisi ascii yang mirip dengan contoh di bawah ini, sesuai dengan kisi rata untuk nomor input pada gambar di atas. Whitespace terkemuka dan tertinggal ok.

Ini golf kode, dengan aturan standar.

Output sampel

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#####
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++

Tiga versi warna untuk N = 4, terima kasih kepada @BruceForte:

#oo+++oooo
o##+++oooo
o##+++####
+++ooo####
+++ooo####
+++ooo####
oo####++++
oo####++++
oo####++++
oo####++++
Jonah
sumber
6
Teorema empat warna: D
Leaky Nun
1
Bisakah Anda menambahkan output untuk N = 5?
Uriel
1
@Uriel Selesai. Lihat hasil edit saya.
Jonah
Terima kasih! Juga, dapatkah saya mengganti @ dan os hanya di strip luar di N = 4? Atau haruskah output menjadi substitusi ketat dari teks-teks ini dengan rangkaian karakter lain?
Uriel
@Uriel switching tidak masalah. Yang penting adalah warna-warna yang berdekatan tidak saling bertentangan, sehingga polanya terlihat.
Jonah

Jawaban:

17

MATL , 30 28 27 byte

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

Cobalah online!

Fitur bonus:

  • Untuk 26 byte , versi modifikasi berikut menghasilkan output grafis :

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

    Cobalah di MATL Online!

  • Gambar memohon beberapa warna , dan harganya hanya 7 byte:

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

    Cobalah di MATL Online!

  • Atau gunakan versi yang lebih panjang (37 byte) untuk melihat bagaimana matriks karakter dibangun secara bertahap :

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

    Cobalah di MATL Online!

Keluaran contoh

Untuk input 8, berikut ini menunjukkan versi dasar, output grafis, dan output grafis warna.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Penjelasan

Prosedur umum

Matriks numerik dibangun dari lapisan luar ke dalam dalam Nlangkah-langkah, di mana Ninputnya. Setiap langkah menimpa bagian dalam (kiri-atas) dari matriks sebelumnya. Pada akhirnya, angka-angka dalam matriks yang diperoleh diubah menjadi karakter.

Contoh

Untuk input 4, matriks pertama adalah

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

Sebagai langkah kedua, matriks

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

ditimpa ke bagian atas yang terakhir. Kemudian hal yang sama dilakukan dengan

6 5 5
5 4 4
5 4 4

dan akhirnya dengan

3

Matriks yang dihasilkan adalah

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

Terakhir, 30ditambahkan ke setiap entri dan angka yang dihasilkan diinterpretasikan sebagai codepoint dan dikonversi ke karakter (dengan demikian dimulai dari 33, sesuai dengan !).

Konstruksi matriks perantara

Untuk input N, pertimbangkan penurunan nilai kdari Nke 1. Untuk masing-masing k, vektor bilangan bulat dari 1ke k*(k+1)dihasilkan, dan kemudian setiap entri dibagi dengan kdan dibulatkan ke atas. Sebagai contoh, untuk k=4ini memberi (semua blok memiliki ukuran kkecuali yang terakhir):

1 1 1 1 2 2 2 2 3 3

sedangkan untuk k=3hasilnya adalah (semua blok memiliki ukuran k):

1 1 1 2 2 2

Vektor ini ditambahkan, elemen-bijaksana dengan siaran, ke salinan dirinya sendiri; dan kemudian kditambahkan ke setiap entri. Untuk k=4ini memberi

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

Ini adalah salah satu dari matriks perantara yang ditunjukkan di atas, kecuali bahwa ia dibalik secara horizontal dan vertikal. Jadi yang tersisa adalah membalikkan matriks ini dan menuliskannya di sudut kiri atas matriks "terakumulasi" sejauh ini, diinisialisasi ke matriks kosong untuk langkah pertama ( k=N).

Kode

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
Luis Mendo
sumber
Saya tidak tahu MATL sama sekali, tetapi bisakah Anda menyimpan byte dengan mengambil mod10 daripada menambahkan 30 dan mengkonversi ke karakter?
user2390246
Atau bahkan mod4 ...
user2390246
@ user2390246 Apakah Anda bermaksud menjadikannya sebagai angka dengan satu digit dan menghindari konversi menjadi char? Itu tidak akan berhasil, karena matriks numerik akan dicetak dengan spasi di antara angka-angka. Tapi terima kasih untuk idenya :-)
Luis Mendo
Cukup adil. Apa yang terjadi dengan n> 226? Tidakkah itu akan melampaui kisaran karakter yang valid? (Tidak mengejutkan, waktu habis pada TIO, jadi saya tidak bisa memeriksa)
user2390246
@ user2390246 Ya, untuk angka input tinggi ia keluar. Dan jika kita menganggap ASCII chars titik kode maksimum adalah 127, jadi itu keluar lebih cepat. Tetapi seperti yang Anda perhatikan itu kehabisan memori sebelum itu terjadi (matriks char yang dihasilkan terlalu besar). Bagaimanapun, bekerja hingga ukuran input yang diberikan hanya karena keterbatasan memori atau tipe data biasanya diperbolehkan
Luis Mendo
7

Python 2 , 187 178 164 162 152 byte

-8 byte terima kasih kepada Mr.Xcoder
-1 byte terima kasih kepada Stephen
-10 byte terima kasih kepada 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]

Cobalah online!

tongkat
sumber
Untuk saat Anda tiba di rumah, 179 byte .
Tn. Xcoder
@ Mr.Xcoder 178 byte
Stephen
1
Apakah itu diperbolehkan untuk tidak memasukkan jumlah byte nama fungsi lambda Anda ketika Anda menggunakannya secara rekursif, yaitu menggunakan namanya di sisa kode?
Jonathan Frech
sum(range(y))%y->y*~-y/2%y
Jonathan Frech
@ JonathanFrech ya, ketika itu bersifat rekursif pasti ada di sana.
Rod
7

Arang , 50 46 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Versi 50-byte sebelumnya dengan penjelasan: Cobalah online!

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

Catatan: Saya mengulangi karakter daripada mencoba untuk menetapkan karakter secara langsung lkarena Anda tidak bisa langsung menetapkan hasil pengindeksan string ke variabel karena ini merupakan konstruksi yang ambigu di Charcoal. Untungnya jumlah byte sama.

Neil
sumber
Secara teknis Anda bisa, dengan variabel ASCII karena urutan argumennya terbalik (perhatikan bahwa perlu operator untuk mengakses sehingga masih kurang golf)
ASCII-only
5

C (gcc) , 135 128 120 byte

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;}

Cobalah online!

Hanya menggunakan tiga warna.

Secara konseptual, bekerja pada grid yang diputar 180 derajat:

000111
000111
000111
111220
111220
111001

Dan menghitung warna sesuai dengan rumus:

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
nwellnhof
sumber
1
123 byte.
Jonathan Frech
@ JonathanFrech Ini bukan C yang valid dan putus dengan gcc -O2.
nwellnhof
Cukup adil; apakah mungkin kode kedua hanya berfungsi untuk tiga warna karena modulus tiga ( g(i%m,i/m,n)%3)?
Jonathan Frech
Sarankan x/k&&y/kalih-alihx>=k&y>=k
ceilingcat
2

R , 131 126 123 byte

3 byte disimpan berkat @Giuseppe

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,,"")}

Cobalah online!

Ini menggunakan algoritma yang sama dengan jawaban MATL @LuisMendo . Satu-satunya perbedaan adalah bahwa alih-alih mengkonversi ke karakter, matriks adalah output dengan semua nilai mod4 untuk memastikan bahwa setiap elemen adalah karakter ascii tunggal.

pengguna2390246
sumber
1
123 byte! Saya membawa forloop kembali untuk -1 byte :)
Giuseppe
1

Python 2 , 176 175 byte

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)

Cobalah online!

TFeld
sumber
Jika Anda mendefinisikan J="".join;(+10 byte) dan mengganti keduanya "".joins (-2 * 7 = -14 byte) dengan J(+2 byte), Anda dapat menyimpan byte (karena harus ada ruang tambahan setelah print; +1 byte) .
Jonathan Frech