Обобщенная матрица трассировки


23

Вдохновение.

Дано (любыми средствами):

  • Функция черного ящика с двумя аргументами (или один аргумент, состоящий из двухэлементного списка) , (вход и выход 1, 2, 3,…)f: ℤ+ × ℤ+ → ℤ+
  • Строго положительная целочисленная матрица с минимум двумя строками и двумя столбцами

вернуть трассировку функции матрицы .

Что такое функция трассировки ?

Трасса нормальной матрицы - это сумма большой диагонали (сверху-слева-внизу-справа) матрицы:

[[1,2,3],[4,5,6],[7,8,9]][1,5,9]1+5+915

Но вместо суммирования мы хотим применить fпо диагонали:

[[1,2,3],[4,5,6],[7,8,9]][1,5,9]f(f(1,5),9)илиf(1,f(5,9))

Пожалуйста, укажите, используете ли вы слева направо или справа налево.

Данная матрица и все промежуточные значения будут строго положительными целыми числами в целочисленной области вашего языка. Матрица может быть не квадратной.

Примеры

f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]]1×5×945

f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]]→ →1591

f(x,y) = x-y, [[4,5,6],[1,2,3]]4-22

f(x,y) = (x+y)⁄2, [[2,3,4],[5,6,7],[8,9,10]]5или7

f(x,y) = x+2y, [[1,2,3],[4,5,6],[7,8,9]]47или29

f(x,y) = max(x,y), [[1,2,3],[4,5,6],[7,8,9]]max(1,5,9)9

f(x,y) = 2x, [[1,2,3],[4,5,6],[7,8,9]]2или4

f(x,y) = lcm(x,y), [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]lcm(2,2,3)6

Справочная реализация.


Какова диагональ [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]?
полностью человек

3
@totallyhuman:[2,2,3]
Эминья

1
Черт возьми, я прочитал заголовок как «Трансляция обобщенной матрицы» и был очень разочарован, когда страница загрузилась
tar

Ответы:


9

R , 40 30 байт

function(m,F)Reduce(F,diag(m))

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

Проверьте контрольные примеры.

Пересекает по диагонали, так что слева направо в этом случае. Для арифметических операторов вы можете использовать "+"или обратные пометки вокруг операторов ( +,*,-,%/%,^,%%)

Довольно просто: ReduceR эквивалентно a fold, а диагональ матрицы - это те элементы, a_ijгде i==j, т. Е. Где индексы rowи column совпадают. diagимеет соответствующее поведение для неквадратных матриц.


8

Haskell , 39 байт

Спасибо @Laikoni за помощь в исправлении ранее недействительного решения!

f!m=foldl1 f[h|h:_<-zipWith drop[0..]m]

Партнеры слева, попробуйте онлайн! (заменить foldl1на foldr1для правоассоциативной)


как насчет foldl1 f$zipWith(!!)m[0..]?
гордый haskeller

@proudhaskeller: Это то, что уже пробовали другие, но это не дает результатов на неквадратных матрицах ..
მოიმო 25.01-18

5

Mathematica , 16 байтов

-1 байт благодаря Мартину Эндеру.

#~Tr~Fold[g]@*0&

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

Альтернативное решение, 17 байтов

Fold[g]@*Diagonal

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


17 байтов (функции черного ящика могут быть приняты под заданным именем)
Mr. Xcoder

Этот @*{}синтаксис не имеет большого смысла (вы, вероятно, имели в виду @*List), но тот факт, что он работает в любом случае, довольно крутой. На самом деле, это означает , что вы можете заменить {}с 0и сохранить байты.
Мартин Эндер

@MartinEnder У меня действительно было Listпервое, но я попробовал {}просто так, и был очень удивлен, что это сработало. Имеет смысл, но как 0работает? o0
полностью человек

1
@totallyhuman Так же, как и {}. В настоящее время вы используете {}как функцию (или фактически как «голову», используя терминологию Mathematica). Если бы вы использовали общий fтам, вы бы получили f[1,2,3](если это диагональ). Но с {}тобой получится {}[1,2,3]. Это совершенно бессмысленное выражение, но сами головы могут быть произвольными выражениями, и если Mathematica не знает, что с ними делать, она просто оставляет их такими, какие они есть. Большинство функций манипулирования списками в Mathematica фактически работают с выражениями с произвольным заголовком, а в случае Foldзаголовок просто игнорируется. [tbc]
Мартин Эндер

Таким образом, вы можете использовать 0вместо головы, которая дает, 0[1,2,3]который все еще не имеет смысла, но работает все равно.
Мартин Эндер

4

Октава , 61 57 53 байта

function m=g(f,m)for i=diag(m)'(2:end)m=f(m(1),i);end

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

Определяет функцию, gкоторая принимает дескриптор функции fи матрицу m. На первой итерации m(1)возвращает верхний левый матричный элемент; после этого он просто возвращается m.



@Giuseppe Это то, что я сделал с моей первоначальной 61-байтовой версией. Конечно, я должен был объединить сильные стороны моей 57- и 61-байтовой версии, которая дает 53-байтовый ответ. Спасибо, что заставили меня взглянуть на это снова!
Sanchises


3

Haskell , 47 45 42 байта

f%((h:t):r)|[]<-t*>r=h|x<-tail<$>r=f h$f%x

Попробуйте онлайн! Определяет функцию, (%)которая принимает функцию и матрицу в качестве списка списков в качестве входных данных.

Функция складывается справа налево:

f % [[1,2,3], -> f 1 ( f % [[5,6],   -> f 1 ( f 5 ( f % [[9]] ) ) -> f 1 ( f 5 ( f 9 ) ) )
     [4,5,6],               [8,9]] )
     [7,8,9]]

f % ((h:t):r)              -- (h:t) is the first row and r the remaining rows
 | [] <- t *> r = h         -- a shorter way of checking wether t==[] or r==[]
 | x<-tail<$>r = f h $ f%x -- apply f to h and the result of recursively calling (%) on
                           -- the remaining matrix with the first column removed

Изменить: -2 байта благодаря BMO и -3 байта благодаря Zgarb !


1
43 байта с помощью $условного упрощения и с *>.
Згарб

@Zgarb Хорошая идея для использования *>!
Лайкони

3

APL (Dyalog Unicode) , 7 байт ( SBCS Адама )

⎕/1 1⍉⎕

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

-3 благодаря предложению преобразовать это в полную программу от Адама .

Справа налево.


Нет необходимости использовать SBCS Адама здесь: вы можете просто использовать Dyalog Classic.
Захари

@ Zacharý Дело в том, что я отвечаю в Dyalog Unicode, со временем Classic становится устаревшим.
Эрик Outgolfer

Не кодовая страница, хотя кодовая страница будет жить
Zacharý

@ Zacharý Хорошо, давайте будем последовательными. : P
Эрик Outgolfer




2

JavaScript (ES6), 58 56 байт

g=(f,a,r=a[i=0][0],e=a[++i]&&a[i][i])=>e?g(f,a,f(r,e)):r

Складывается слева направо. Редактировать: Сохранено 2 байта, используя тот факт, что массив является строго положительным. Альтернативное решение, также 56 байтов:

(f,a,g=r=>(e=a[++i]&&a[i][i])?g(f(r,e)):r)=>g(a[i=0][0])

Это не выглядит , как вам нужно , 1/и вы можете сэкономить еще 2 байта, перемещая некоторые вещи вокруг: f=>a=>(h=r=>(e=a[++i]&&a[i][i])?h(f(r,e)):r)(a[i=0][0]). TIO
Лохматый

@ Шэгги О, это точно положительно, я этого не видел.
Нил

Очевидно, мы можем предположить, что функции черного ящика назначены предопределенной переменной, поэтому вы можете сохранить 2 байта, если хотите воспользоваться этим.
Лохматый

@ Shaggy На самом деле я думаю, что это сэкономит 4 байта (2x f,) от первой версии?
Нил

Вы правы; извините, забыл считать f,при gповторном звонке .
Лохматый

2

JavaScript, 46 байт

f=>a=>a.reduce((p,l,i)=>l[i]?f(p[0]|p,l[i]):p)

Благодаря @Shaggy, используйте побитовый или сохранить один байт. Это волшебство.


Это не работает, если матрица имеет больше строк, чем столбцов.
Лохматый

@Shaggy так грустно, 47 байт теперь ...
TSH

Да, это то, что у меня тоже было изначально. Я только собирался отредактировать исправление в моем решении, но вы меня тоже обошли :( Я думаю, что вы можете получить один байт обратно, хотя, используя побитовое ИЛИ.
Shaggy

@Shaggy так магия
TSH

Забыл упомянуть: очевидно, мы можем предположить, что функции черного ящика назначены предопределенной переменной, поэтому вы можете сохранить 3 байта, если хотите воспользоваться этим.
Лохматый

2

Java 8, 88 81 70 байт

m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}}

Складывается [[1,2,3],[4,5,6],[7,8,9]]в f(f(1,5),9).

-7 байтов косвенно благодаря @KamilDrakari , используя тот же прием, который он делал в своем ответе на C # : вместо того, чтобы иметь максимальную границу для цикла, основанного на строках / столбцах, просто попробуйте поймать ArrayIndexOutOfBoundsException.
-11 байт catch(Exception e)с заменой на finally.

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

Старый 88 байт ответа:

m->{int r=m[0][0],i=1;for(;i<Math.min(m.length,m[0].length);)r=f(r,m[i][i++]);return r;}

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

Объяснение:

m->{                   // Method with integer-matrix parameter and integer return-type
  int r=m[0][0],       //  Start the result at the integer of position 0,0 (0-indexed)
      i=1;             //  Start the index at 1 (0-indexed)
  try{for(;;)          //  Loop indefinitely
    r=f(r,m[i][i++]);} //   Call f with the result + next diagonal cell as arguments
                       //   (and increase `i` by 1 with `i++` afterwards)
  finally{             //  If an ArrayIndexOutOfBoundsException occurred we're done,
   return r;}}         //   in which case we return the result-integer

Формат ввода черного ящика:

Предполагается, что именованная функция int f(int x,int y)присутствует, что разрешено в соответствии с этим мета-ответом .

У меня есть абстрактный класс, Testсодержащий функцию по умолчанию f(x,y), а также лямбду выше:

abstract class Test{
  int f(int x,int y){
    return x+y;
  }

  public java.util.function.Function<int[][],Integer>c=
    m->{int r=m[0][0],i=1;for(;i<Math.min(m.length,m[0].length);)r=f(r,m[i][i++]);return r;}
  ;
}

Для тестовых случаев я перезаписываю эту функцию f. Например, первый тестовый пример называется так:

System.out.println(new Test(){
  @Override
  int f(int x,int y){
    return x*y;
  }
}.c.apply(new int[][]{
  new int[]{1,2,3},
  new int[]{4,5,6},
  new int[]{7,8,9}
}));

2

Атташе , 14 байт

Fold#/Diagonal

Попробуйте онлайн! Установите fи позвоните как f[function, array].

объяснение

Это форк двух функций: Foldи /Diagonal. Это для аргументов fи aэквивалентно:

Fold[f, (/Diagonal)[f, a]]

/при монадическом применении к функции возвращает функцию, примененную к последнему аргументу. Итак, это эквивалентно:

Fold[f, Diagonal[a]]

Это сгибает функцию fпо главной диагонали a.


Язык домашнего
приготовления,

@ Adám; D, да!
Конор О'Брайен

2

AWK , 77 байт

func z(F,M,r){for(e=1;e<M[1]&&e<M[2];)r=@F(r==""?M[1,1]:r,M[++e,e])
return r}

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

Мне было любопытно, AWKможно ли вообще заниматься функциональным программированием. Я думаю, что это имеет значение.

«Матрица» определяется как стандартный ассоциативный массив с дополнительными полями M[1]=#rowsи M[2]=#columns. Имя функции передается в виде строки, которая оценивается через @F(...)синтаксис. Оценка выполняется слева направо. rПараметр является заполнителем для предотвращения перезаписи существующего rпеременного и избежать необходимости повторной инициализации для каждого вызова. Обычно для обозначения таких заполнителей добавляется дополнительное пространство AWK, но это кодовый гольф, поэтому каждый байт считается. :)

Ссылка TIO реализует все контрольные примеры.


2

05AB1E , 15 10 байт

Складывается справа налево.
Сохранено 5 байтов с использованием новой встроенной функции, предложенной Кевином Круйссеном.

Å\`[.g#I.V

объяснение

Работает так же, как и в старой версии, за исключением того, что Å\это новая встроенная функция нажатия на основную диагональ.

Попробуйте онлайн! или как тестовый набор

Старая версия

¬g£vyNè}[.g#I.V

Попробуйте онлайн! или как тестовый набор

объяснение

¬                 # get the head of the input (first row)
 g                # get its length (number of columns)
  £               # take that many rows from input
   v              # for each row_index, row (N,y) do:
    y             # push the row
     Nè           # get the nth element of the row
       }          # end loop
        [.g#      # loop until one value remain on the stack
            I.V   # run the input function

1
¬g£vyNè}[можно Å\`[сейчас, сэкономив 5 байт.
Кевин Круйссен

1

Шелуха , 7 байт

Спасибо @Zgarb за исправление моего представления!

Ḟ₁§z!Tŀ

Партнеры слева, попробуйте онлайн! (для правоассоциативной версии просто замените на F)

объяснение

К сожалению, нет простого способа получить диагональ матрицы, поэтому большинство байтов предназначены для этого:

Ḟ₁§z!Tŀ  -- function ₁ is the function and matrix A implicit, example: 
  §      -- fork A
     T   -- | transpose A: [[1,4,7],[2,5,8],[3,6,9]]
      ŀ  -- | enumerate A: [1,2,3]
   z!    -- and zipWith index: [1,5,9]
Ḟ₁       -- right fold function

Да, встроенный для анти-диагоналей, но не для диагоналей‽
Адам

2
@ Adám Полагаю, это потому, что вы можете вычислять антидиагонали бесконечных матриц, но не диагонали.
Мартин Эндер

1

SNOBOL4 (CSNOBOL4) , 86 байт

T	I =1
	T =M<1,1>
I	I =I + 1
	T =EVAL(F '(T,M<I,I>)')	:S(I)F(RETURN)
	DEFINE('T(M,F)')

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

Определяет функцию T(для TRACE), которая принимает ARRAYи строку, Fкоторая является именем функции. Складывается слева направо.

Использование косвенной ссылки ( $) не работает с функциями. Таким образом, использование EVALи передача строки имени является единственным способом получить функцию черного ящика в SNOBOL.

Кроме того, довольно больно определять массивы; однако, поскольку причиной являются недопустимые ссылки на массивы FAILURE, это работает для неквадратных массивов - если значение Iвыходит за пределы любого из измерений, F(RETURN)вынуждает функцию возвращаться.

Редактировать:

Возможно, основываясь на этом мета-посте , я могу предположить, что функция «черный ящик» Fопределена под именем F, что уменьшило бы ее до 75 байт (исключите использование EVALи ,Fв определении функции). Однако я предпочитаю эту версию, поскольку она ближе к передаче ссылки на функцию.



1

tinylisp , 79 байт

(load library
(d D(q((M)(i(h M)(c(h(h M))(D(map t(t M))))(
(q((F M)(foldl F(D M

Последняя строка - это безымянная лямбда-функция, которая принимает функцию и матрицу и возвращает матричную трассировку. След является левоассоциативным (т.е. f(f(1,5),9)). Попробуйте онлайн!

Ungolfed

Мы определяем вспомогательную функцию для вычисления диагонали; тогда generalized-traceэто просто небольшая оболочка для библиотечной функции foldl.

(load library)

(def diagonal
 (lambda (matrix)
  (if (head matrix)
   (cons
    (head (head matrix))
    (diagonal (map tail (tail matrix))))
   nil)))

(def generalized-trace
 (lambda (func matrix)
  (foldl func (diagonal matrix))))

При рекурсивном вычислении диагонали мы проверяем, (head matrix)верно ли это. Если в матрице нет строк, это будет пустой список (nil), а headnil - nil - falsey. Или, если в матрице нет столбцов, ее первая строка (заголовок) будет пустым списком (ноль) - фальси. Иначе будет непустой первый ряд, что является правдой.

Итак, если первая строка не существует или пуста, мы возвращаем ноль. В противном случае, если есть непустая первая строка, мы берем (head (head matrix))- первый элемент первой строки - и cons(добавляем) его к результату рекурсивного вызова. Аргументом для рекурсивного вызова является - (map tail (tail matrix))то есть взять все строки, кроме первой, и взять все элементы, кроме первого, в каждой строке.



1

C # (компилятор Visual C #) , 72 69 60 байт

m=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

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

try/catch позволяет правильно достичь диагонали, просто пройдя по ней и заканчивая вне границ.

Сохранено 3 байта, поскольку, как указал Кевин Круйссен, можно предположить, что функции черного ящика существуют под определенным именем .

9 байтов сохранены путем возврата через изменение аргумента .

Таким образом, функция вызывается путем сохранения нужной функции под именем f, вызова trace(matrix)и сохранения результата в matrix[0][0].

В качестве альтернативы, если вам действительно нравится многословие,

C # (компилятор Visual C #) , 97 + 13 = 110 78 69 байт

(int[][]m)=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

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

32 байта были сохранены с использованием предопределенной функции, поскольку отсутствие функции в качестве параметра позволило удалить Systemимпорт и длинный Funcуниверсальный тип.


Хороший трюк с пробной ловлей. Я был в состоянии гольф 7 байт на моем Java 8 ответ (даже если я должен использовать catch(Exception e)вместо catch:) EDIT:. О, был в состоянии заменить catch(Exception e)с , finallyчтобы сохранить больше байтов. Еще раз спасибо. +1 от меня.
Кевин Круйссен

@KevinCruijssen Вы также можете получить выгоду от моего новейшего улучшения (хотя я точно не помню, поддается ли Java изменению аргументов)
Камиль Дракари

Спасибо, что дал мне знать. Хотя это возможно в Java, это означает, что мне придется изменить finallyна catch(Exception e), потому что я больше не возвращаюсь в наконец. Так что m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}}(73 байта), к сожалению, для меня больше по сравнению с моим текущим ответом m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}}(70 байтов), но действительно хороший способ сохранить байты в вашем ответе! :) Жаль, что я могу только +1 ваш ответ один раз.
Кевин Круйссен

1

JavaScript, 61 57 56 52 50 44 42 байта

Уменьшает слева направо. Предполагается, что функция назначена переменной f, в соответствии с этим мета-постом, представленным моему вниманию Mr. Xcoder & totallyhuman. Не могу сказать, поскольку я согласен с этим, так как это прямо противоречит нашему существующему консенсусу, что мы можем не предполагать, что входные данные назначены предварительно определенной переменной, но я пока возьму несколько сохраняющихся байтов.

a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x

Тестовые случаи

g=
a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x
o.innerHTML=[[`f(x,y) = xy`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x*y,45],[`f(x,y) = x<sup>y</sup>`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x**y,1],[`f(x,y) = x-y`,[[4,5,6],[1,2,3]],(x,y)=>x-y,2],[`f(x,y) = <sup>(x+y)</sup>⁄<sub>2</sub>`,[[2,3,4],[5,6,7],[8,9,10]],(x,y)=>(x+y)/2,7],[`f(x,y) = x+2y`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x+2*y,29],[`f(x,y) = max(x,y)`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>Math.max(x,y),9],[`f(x,y) = 2x`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>2*x,4],[`f(x,y) = lcm(x,y)`,[[2,2,2],[2,2,3],[2,3,3],[4,4,4]],(x,y)=>-~[...Array(x*y).keys()].find(z=>!(++z%x|z%y)),6]].map(([a,b,c,d],e)=>`Test #${++e}:  ${a}\nMatrix:   ${JSON.stringify(b)}\nFunction: ${f=c}\nResult:   ${g(b)}\nExpected: ${d}`).join`\n\n`
<pre id=o></pre>


1

APL NARS, 20 байтов, 10 символов

{⍺⍺/1 1⍉⍵}

тест:

  f←{⍺⍺/1 1⍉⍵}
  ⎕←q←3 3⍴⍳10    
1 2 3
4 5 6
7 8 9
  ×f q
45
  *f q
1
  {⍺+2×⍵}f q
47
  ⌈f q
9
  {2×⍺+0×⍵}f q
2
  -f ⊃(4 5 6)(1 2 3)
2
  {(⍺+⍵)÷2}f ⊃(2 3 4)(5 6 7)(8 9 10)
5
  ∧f ⊃(2 2 2)(2 2 3)(2 3 3)(4 4 4)
6

Отличная работа. Хотя я думаю, что вы пришли к этому самостоятельно, это похоже на оригинальное решение Эрика Аутгольфера .
Адам

0

Желе , 5 байт

Слева направо.

ŒDḢç/

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

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



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.