Узагальнений матричний слід


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
Блін, я прочитав заголовок як "Узагальнений матричний транс" і сильно розчарувався, коли завантажувалася сторінка
тар

Відповіді:


9

R , 40 30 байт

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

Спробуйте в Інтернеті!

Перевірте тестові випадки.

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

Досить прямо: ReduceR еквівалентно a fold, а діагональ матриці - це ті елементи, a_ijде i==j, тобто, де показники rowі column однакові. diagмає відповідну поведінку для неквадратичних матриць.


8

Хаскелл , 39 байт

Дякую @Laikoni за допомогу мені виправити раніше недійсне рішення!

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

Асоціатори зліва, спробуйте це в Інтернеті! (Замінити foldl1на foldr1для правоассоціатівной)


як щодо foldl1 f$zipWith(!!)m[0..]?
гордий haskeller

@proudhaskeller: Це вже намагалися інші, але це не вдається на
неквадратичних

5

Математика , 16 байт

-1 байт завдяки Мартіну Ендеру.

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

Спробуйте в Інтернеті!

Черговий розчин, 17 байт

Fold[g]@*Diagonal

Спробуйте в Інтернеті!


17 байт (функції чорної скриньки можна припустити під заданим іменем)
Містер 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 байти. Дякую, що змусили мене ще раз на це поглянути!
Санчіз


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 завдяки пропозиції перетворити це на повну програму від Adám .

Праворуч наліво.


Тут не потрібно використовувати SBCS Adám: ви можете просто використовувати Dyalog Classic.
Zacharý

@ Zacharý Справа в тому, що я відповідаю в Dyalog Unicode, класика з часом застаріла.
Ерік Аутгольфер

Не кодова сторінка, хоча кодова сторінка буде жити
Zacharý

@ Zacharý Що ж, давайте швидше будемо послідовними. : P
Ерік Аутгольфер




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
Shaggy

@Shaggy О, це абсолютно позитивно, я цього не бачив.
Ніл

Мабуть, можна припустити, що функції чорного поля призначені за попередньо визначеною змінною, щоб ви могли зберегти 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 so sad, 47 bytes now ...
tsh

Так, це теж було у мене спочатку. Якраз збирався відредагувати виправлення в моєму рішенні, але ви теж мене побили :( Я думаю, ви можете отримати один байт назад, хоча, скориставшись бітом АБО.
Shaggy

@Shaggy so magic
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

Attache , 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 так!
Conor O'Brien

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

Так, вбудований для діагоналей, а не для діагоналей
Adám

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

тинілісп , 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)). Спробуйте в Інтернеті!

Безумовно

Ми визначаємо хелперну функцію для обчислення діагоналі; то 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)Обчислюючи діагоналі рекурсивно, ми перевіряємо, чи правда. Якщо матриця поза рядками, це буде порожній список (нуль), а headнуль - нуль - фальси. Або, якщо матриця поза стовпцями, її першим рядком (головою) буде порожній список (нуль) - фальси. Інакше вийде непорожній перший ряд, який є тризубним.

Отже, якщо перший рядок не існує або порожній, повертаємо нуль. В іншому випадку, якщо є непорожній перший рядок, ми беремо (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 bytes saved by using a predefined function, because not taking the function as a parameter allowed removing the System import and the long Func generic type.


Nice trick with the try-catch. I've been able to golf 7 bytes on my Java 8 answer (even though I have to use catch(Exception e) instead of catch. :) EDIT: Oh, been able to replace the catch(Exception e) with finally to save more bytes. Thanks again. +1 from me.
Kevin Cruijssen

@KevinCruijssen you may also be able to benefit from my newest improvement (though I don't remember for sure whether Java is amenable to modifying arguments)
Kamil Drakari

Thanks for letting me know. Although it is possible in Java, it means I'll have to change the finally into catch(Exception e), because I'm not returning inside the finally anymore. So m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}} (73 bytes) is unfortunately longer for me in comparison to my current answer m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}} (70 bytes) But indeed a nice way to save bytes in your answer! :) Too bad I can only +1 your answer once.
Kevin Cruijssen

1

JavaScript, 61 57 56 52 50 44 42 bytes

Reduces left to right. Assumes the function is assigned to variable f, as per this meta post brought to my attention by Mr. Xcoder & totallyhuman. Can't say as I agree with it as it directly contradicts our existing consensus that we may not assume input is assigned to a pre-defined variable, but I'll take the few bytes saving for now.

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

Test Cases

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 bytes, 10 chars

{⍺⍺/1 1⍉⍵}

test:

  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

Good job. While I think you arrive to this on you own, it happens to be identical to Erik the Outgolfer's original solution.
Adám

0

Jelly, 5 bytes

Left-to-right.

ŒDḢç/

Try it online!

Disclaimer: I do not know if this an acceptable input method for black-box functions. This assumes that the function is implemented in the link above, and is thus "named" (that is, it's callable with) ç, but otherwise I have no way to assign it to ç. If anyone has more experience with Jelly + black box functions, I would appreciate thoughts. After spending some time in chat, we figured that using ç might indeed be valid.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.