Визуализируйте теорему Никомаха


35

Теорема Ничомачуса связывает квадрат суммы с суммой кубов:

Теорема Никомаха

и имеет красивую геометрическую визуализацию:

Визуализация

Задача: Создать 2-ую часть этой визуализации в ascii.

Вам необходимо убедиться, что все ваши визуальные границы поддерживаются вашей диаграммой. Это проще всего сделать с четырьмя «цветами», хотя можно добиться только с тремя (см. Последний пример ниже). С четырьмя цветами вы используете два, чтобы различать области внутри «полосы» (т. Е. Различные части, составляющие один куб), и два, чтобы различать соседние полосы. Вы также можете использовать более четырех цветов, если хотите. Если что-то из этого сбивает с толку, приведенный ниже пример должен прояснить ситуацию.

Ввод, вывод

Входные данные - это одно целое число, большее 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#####
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++

Трехцветная версия для N = 4, благодаря @BruceForte:

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

6
Теорема о четырех цветах: D
Утечка Монахиня

1
Можете ли вы добавить вывод для N = 5, пожалуйста?
Уриэль

1
@Uriel Готово. Смотрите мое редактирование.
Иона

Благодарность! Кроме того, я могу переключать @ и os только во внешней полосе в N = 4? Или вывод должен быть строгой заменой этих текстов другой кодировкой?
Уриэль

@ Уриэль переключение в порядке. Все, что имеет значение, - то, что смежные цвета не конфликтуют, так что образец виден.
Иона

Ответы:


17

MATL , 30 28 27 байт

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

Попробуйте онлайн!

Бонусные возможности:

  • Для 26 байтов следующая модифицированная версия производит графический вывод :

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

    Попробуйте это в MATL Online!

  • Изображение требует цвета и стоит всего 7 байт:

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

    Попробуйте это в MATL Online!

  • Или используйте более длинную версию (37 байт), чтобы увидеть, как постепенно строится матрица символов :

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

    Попробуйте это в MATL Online!

Пример выходов

Для ввода 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рассмотрим уменьшение значений kот Nдо 1. Для каждого генерируется kвектор целых чисел от 1до k*(k+1), а затем каждая запись делится на kи округляется в большую сторону . Как пример, для k=4этого дает (все блоки имеют размер, kкроме последнего):

1 1 1 1 2 2 2 2 3 3

тогда как для k=3результата будет (все блоки имеют размер 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 Вы хотите сохранить их как числа с одной цифрой и избежать преобразования в символ? Это не сработает, потому что числовая матрица будет напечатана с пробелами между числами. Но все равно спасибо за идею :-)
Луис Мендо

Справедливо. Что происходит с n> 226? Разве это не выйдет за пределы диапазона допустимых символов? (Неудивительно, что
тайм-

@ user2390246 Да, для больших цифр ввода это выходит наружу. И если мы рассмотрим символы ASCII, максимальная кодовая точка равна 127, поэтому он выходит наружу еще раньше. Но, как вы заметили, до этого не хватает памяти (полученная матрица символов слишком велика). В любом случае, работа с заданным размером ввода только из-за ограничений памяти или типа данных обычно разрешается
Луис Мендо

7

Python 2 , 187 178 164 162 152 байта

-8 байт благодаря Mr.Xcoder
-1 байт благодаря Стивену
-10 байт благодаря Джонатану Фреху

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


1
Разрешено ли не включать количество байтов имени вашей лямбда-функции, когда вы используете его рекурсивно, то есть используете его имя в остальной части кода?
Джонатан Фрех

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 , так как его аргумент для того , сторнируется (заметим , что она нуждается оператор доступа , так что все еще меньше golfy)
ASCII-только

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
floorcat

2

R , 131 126 123 байт

3 байта сохранены благодаря @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,,"")}

Попробуйте онлайн!

При этом используется тот же алгоритм, что и в ответе @LuisMendo на MATL . Единственная разница состоит в том, что вместо преобразования в символы матрица выводится со всеми значениями mod4, чтобы каждый элемент представлял собой один символ ascii.


1
123 байта! Я вернул forцикл на -1 байт :)
Джузеппе

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 s (-2 * 7 = -14 байт) на J(+2 байт), вы можете сохранить байт (так как после print; +1 байт должен быть дополнительный пробел ) ,
Джонатан Фрех,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.