Фон
Арифметические атомы желе векторизуются автоматически. На самом деле, x + y четко определено всякий раз, когда x и y являются числами или рваными массивами чисел. Исходный код Jelly реализует это поведение с использованием универсального векторизатора, но для этой задачи мы рассмотрим только добавление целых и вложенных целочисленных массивов.
Определения
Определите глубину x как 0, если x является целым числом, как 1, если это (возможно, пустой) плоский массив целых чисел, и как n + 1, если он содержит хотя бы один элемент глубины n и не имеет элементов глубины k> п .
Таким образом, 1 имеет глубину 0 , [] и [1] и [1, 1] имеют глубину 1 , [[], []] и [[1], [1]] и [[1]] и [1 , []] имеют глубину 2 , [1, [1, [1]]] имеют глубину 3 и т. д.
Операция x + y определяется следующим образом.
Если x и y имеют глубину 0 , вернуть их сумму.
Если x и y имеют одинаковую, но положительную глубину, рекурсивно примените + ко всем элементам x и соответствующим элементам y .
Если x и y имеют разную длину, добавьте хвост более длинного массива к массиву сумм.
Вернуть результат.
Если глубина x строго меньше, чем глубина y , рекурсивно примените + к x и всем элементам y и верните результат.
Сделайте обратное, если глубина y строго меньше, чем x .
Например, рассмотрим операцию [1, [2, 3], [4]] + [[[10, 20], [30], 40, 50], 60] .
Глубина левого аргумента равна 2 , а глубина правого аргумента равна 3 , поэтому мы вычисляем [1, [2, 3], [4]] + [[10, 20], [30], 40, 50 ] и [1, [2, 3], [4]] + 60 .
[1, [2, 3], [4]] и [[10, 20], [30], 40, 50] оба имеют глубину 2 , поэтому мы вычисляем 1 + [10, 20] , [2, 3] + [30] и [4] + 40 .
1 + [10, 20] = [1 + 10, 1 + 20] = [11, 21]
[2, 3] + [30] = [2 + 30, 3] = [32, 3]
Обратите внимание, что 3 остается нетронутым, поскольку у него нет соответствующего элемента.
[4] + 40 = [4 + 40] = [44]
50 не имеет соответствующий элемент, так что результат [[[11, 21], [32, 3], [44], 50]] .[1, [2, 3], [4]] + 60 = [1 + 60, [2, 3] + 60, [4] + 60] = [61, [2 + 60, 3 + 60], [ 4 + 60]] , что приводит к [61, [62, 63], [64]] .
Окончательный результат [[[11, 21], [32, 3], [44], 50], [61, [62, 63], [64]]] .
задача
Напишите программу или функцию, которая принимает два целых числа, два вложенных массива целых чисел или их комбинацию в качестве входных данных и возвращает их сумму, как определено выше.
Если ваш язык имеет несколько массивоподобных типов (списки, кортежи, векторы и т. Д.), Вы можете выбрать любой из них для ответа. Тип возвращаемого значения должен соответствовать типу аргумента.
Чтобы предотвратить скучные и непобедимые решения, если язык имеет это точную работу как встроенный, вы не можете использовать этот язык.
Все встроенные модули всех других языков разрешены. Если ваш язык позволяет это сделать, вы можете перегрузить и / или переопределить встроенное дополнение.
Это код-гольф , поэтому выигрывает самый короткий код в байтах.
Контрольные примеры
0 + 0 = 0
[-1, 0, -1] + [1] = [0, 0, -1]
[] + [0] = [0]
[] + 0 = []
[] + [] = []
[[], 0] + [] = [[], []]
[1, 2, 3] + 10 = [11, 12, 13]
[1, 2, 3] + [10] = [11, 2, 3]
[1, 2, 3] + [10, [20]] = [[11, 12, 13], [21, 2, 3]]
[1, 2, 3, []] + [10, [20]] = [11, [22], 3, []]
[1, [2, [3, [4]]]] + [10, [20]] = [[11, [21]], [[12, [22]], [13, [24]]]]
Чтобы создать больше тестовых случаев, вы можете использовать эту программу Jelly .
Ответы:
Pyth, 42 байта
Тестирование
Последние 4 байта просто запускают функцию на входе.
источник
APL, 44 байта
APL также
+
распределяет по массивам, но достаточно по-другому, так что это не может быть использовано. Однако есть встроенная функция глубины (≡
).Объяснение:
1=≡⍺⍵:⍺+⍵
: если⍺
⍵
обе глубины равны нулю (и, следовательно, глубина⍺ ⍵
равна 1), добавьте их.∆←|≡¨⍺⍵
: Взять абсолютные глубины как⍺
и⍵
и хранить их в∆
. (≡
дает отрицательное значение, если не все элементы имеют одинаковую глубину.)=/∆
: если они имеют одинаковую глубину:↓↑⍺⍵
: заполнить кратчайший массив нулями, чтобы он соответствовал длинному массиву⊃∇¨/
: распределить функцию по обоим массивам</∆
: если глубина⍺
меньше, чем глубина⍵
:⍺∘∇¨⍵
: bind,⍺
а затем наносить на карту⍵
⍵∇⍺
: если больше ничего (так⍵
глубже⍺
), поменяйте местами аргументы и попробуйте снова.источник
Mathematica, 122 байта
Определяет рекурсивную функцию,
f
которая вычисляет сумму. Используя сопоставление с образцом Mathematica, эта функция состоит из четырех отдельных определений:Если глубина
x
больше, чем глубинаy
, поменяйте местами аргументы, чтобы мы могли обрабатывать распределение только в одном направлении (что мы можем сделать, так как сложение коммутативно).Если глубина
x
меньше Thann , что изy
, заменить каждое значение#
вy
сf[x,#]
, который заботится о распределении для аргументов неравной глубины.В противном случае, если один аргумент является списком (что подразумевает, что другой также является списком, поскольку мы знаем, что они имеют одинаковую глубину), мы помещаем оба аргумента в список, дополняем их одинаковой длиной
PadRight[..., Automatic]
(что просто заполняет рваный массив с нулями, чтобы сделать его прямоугольным), а затем использоватьMapThread
для примененияf
к соответствующим парам из двух списков.И, наконец, базовый вариант:
Если ни один из других шаблонов не совпадает, мы должны попытаться добавить два числа, поэтому мы просто делаем это.
источник
Haskell, 150 байт
объяснение
Первая строка определяет алгебраический тип данных
L
, который является либоS
calar (содержащийInt
), либоV
ector (содержащий списокL
s, доступ к которому осуществляется с помощью средства получения записиv
, которое является частичной функциейL → [L]
.)Вторая строка определяет функцию глубины : глубина
V
эктора равна единице плюс ее максимальная глубина. Я добавляюS 0
значения в векторе, так чтоdepth [] == 1 + maximum [depth (S 0)] == 1
. Глубина «всего остального» (скаляр) есть0
.Третья строка определяет базовый случай для
!
(функция сложения): сумма скаляров просто скаляр.Пятая строка определяет вариант,
zipWith (!)
который просто выбирает элементы из самого длинного списка, когда один из них пуст.Четвертая строка разбита на три случая:
Если глубина
x
строго меньше, чем глубинаy
, отобразите(x!)
элементыy
. (Использованиеv
гарантированно будет действительным, какd(y) ≥ 1
.)Если глубина
x
строго больше, переверните аргументы и перезапустите.Если их глубина равна, заархивируйте аргументы вместе с
(!)
. (Использованиеv
гарантированно будет действительным, так как случайd(x) = d(y) = 0
был обработан как базовый вариант.)Контрольные примеры
Потом
show (lArg ! rArg) == "[[11,[21]],[[12,[22]],[13,[24]]]]"
.источник
import
том, что у Ideone есть старый компилятор на Haskell. Современные версии GHC поместить<$>
вPrelude
, так что вам не нужно импортировать ,Control.Applicative
чтобы использовать его в эти дни.Java,
802794754746 байтЯ решил взяться за @ Деннис ♦ за задачу поработать со строками «в крайнем случае», потому что это было, вероятно, «слишком сложно». Кроме того, на худшем языке для игры в гольф.
Массивы на входе разделены запятыми, заключены в квадратные скобки и без пробелов.
Полная программа с функциями, заключенными в класс и с тестовыми примерами
Я мог бы портировать это на C ++ позже, так как это другой язык, который я знаю, который не поддерживает рваные массивы, так как я
почти уверен, чтоон будет короче, чем этот ответ. Это было главным образом доказательством концепции, но любые советы по игре в гольф все равно будут оценены!-31 байт от @ user902383, предлагающего использовать foreach поверх преобразованного массива символов, а затем я немного сэкономил от перестановки блоков if в заключительной части.
источник
Object[]
, которое содержит либо вложенный,Object[]
либоInteger
. Или просто неуниверсальный список.Python 2.7,
261209202198191185197181 байтFGITW тривиальное решение
РЕДАКТИРОВАТЬ: Конечно @ Деннис бьет это
Спасибо @LeakyNun за сохранение 57 байтов с подсказками по лямбда-выражениям и 2 байта из ненужных скобок.
Спасибо @Adnan за 4 байта из-за предложения использовать
type
вместоisinstance
Спасибо @Lynn за 7 байтов с
-~
иmap
Спасибо @FryAmTheEggman за
z>=[]
вместоtype
+12 байт для преобразования лямбды в if else и исправления серьезной ошибки
-16 байт благодаря @Kevin Lau - не Кенни
Попробуйте онлайн
источник
z==[]or`z`>']'and ...
max(d(a)+1for a in z)
на-~max(d(a)for a in z)
экономит байт (потому что вы можете удалить пространство раньшеmax
). Что тогда просто-~max(map(d,z))
.[p(a,b)for a,b in zip(x,y)]
наmap(p,x,y)
. Вы все еще можете сделать это в 3, но вам нужно добавить вызовlist
. Я думаю, вы могли бы также улучшить предложение Линнz>=[]
. Независимо от этого, вы также должны иметь возможность менятьtype
порядок сравнения, чтобы сэкономить место.or`z`>'['
, конечно, но больше не могу менять свой комментарий. Но на самом деле,z>[]
еще короче (==
дело уже решено)!Python 2,
145136 байтПроверьте это на Ideone .
Как это устроено
В Python 2 все целые числа меньше всех словарей, но все списки больше. d рекурсивно вычисляет глубину t , возвращая 0 для целых чисел или увеличенный максимум глубин его элементов и 0 .
t+[0]
избегает специального случая пустого списка.s рекурсивно вычисляет сумму желе x и y .
Если глубина y превышает x ,
s(y,x)
вызывает s с замененными аргументами, убедившись, что d (x) ≤ d (y) .Если у имеет положительную глубину,
map(s,(x,[x]*len(y))[d(x)<d(y)],y)
делает следующее.Если х и у глубины совпадают, он выполняется
map(s,x,y)
, отображая s по всем элементам x и соответствующим элементам y .В случае списков различной длины, карта будет передавать None как левый или правый аргумент для отсутствующих элементов в более коротком списке.
Если X глубина «S ниже , чем у , выполняется
map(s,[x]*len(y),y)
, отображая s (x, ·) над y .Если у (и, следовательно, х ) имеет глубину 0 ,
(x or 0)+(y or 0)
заменяет ложные аргументы ( Нет или 0 ) нулями и возвращает сумму результирующих целых чисел.источник
JavaScript (ES6), 152 байта
источник
Рубин 2,3
143145148149 байтВ Ruby есть все эти маленькие странности в
zip
работе с массивами разной длины иmap
с несколькими аргументами, что делает это довольно забавным для игры в гольф.источник
map
функцию с двумя аргументами, как я ее настроил в конце. Вот версия, отредактированная для 2.1, которая работает, которая настраиваетmap
вызов в конце, чтобы работать. ideone.com/q1jqTAЮлия, 113 байт
Попробуйте онлайн!
Как это устроено
создает 1-байтовый псевдоним для endof , который возвращает длину массива.
определяет функцию глубины. Глубина t равна нулю тогда и только тогда, когда 0t == 0 . Если нет, то t является массивом, и его глубина рассчитывается как увеличенный максимум глубин его элементов и 0 .
[t;0]
добавляет 0 к массиву t , что исключает необходимость в специальном случае пустого массива.Юлия встроенная сумма + уже ведет себя как сумма Джелли, если один из (или оба) ее аргументов является целым числом. Однако для суммирования двух массивов ( + ) требуются массивы одинаковой формы и даже векторизованная сумма ( . + ) Требуются массивы, которые можно транслировать в общую форму.
Мы переопределяем + для пары массивов через
Это не влияет на определение + для аргументов целое число / целое число, массив / целое число или целое число / массив.
(!x,~x)>(!y,~y)
лексикографически сравнивает пары глубин и длин как x, так и y . Если X глубина «S превышает у , или если их глубина совпадает, а длина x превышает y ,y+x
рекурсивно вызывает + с замененными аргументами.В противном случае,
!x<!y
тесты, если х глубина ниже, чем y . Если это так,map(t->x+t,y)
карты x + · над y .Если глубина совпадает,
~x<~y
проверяет, х короче, чем y . Если это так,[x;0]+y
рекурсивно вызывает + после добавления 0 к левому аргументу.Наконец, если глубина и длина одинаковы,
x.+y
карты + для всех элементов x и соответствующих элементов y .источник