12
\$\begingroup\$

Task

Given a matrix of numbers \$M\$ with \$r\$ rows and \$c\$ columns, and the magnification factor \$n\$, build the matrix with \$rn\$ rows and \$cn\$ columns where the original elements are spaced \$n\$ units apart and the gaps are filled by piecewise linear interpolation:

$$ \begin{bmatrix} a_{11} & a_{12} & \cdots \\ a_{21} & a_{22} & \cdots \\ \vdots & \vdots & \ddots \\ \end{bmatrix} \Rightarrow \begin{bmatrix} a_{11} & \frac{(n-1)a_{11} + a_{12}}{n} & \cdots & a_{12} & \cdots \\ \frac{(n-1)a_{11} + a_{21}}{n} & \frac{(n-1) \frac{(n-1)a_{11} + a_{21}}{n} + \frac{(n-1)a_{12} + a_{22}}{n}}{n} & \cdots & \frac{(n-1)a_{12} + a_{22}}{n} & \cdots \\ \vdots & \vdots & \ddots & \vdots \\ a_{21} & \frac{(n-1)a_{21} + a_{22}}{n} & \cdots & a_{22} & \cdots \\ \vdots & \vdots & & \vdots & \ddots \\ \end{bmatrix} $$

Because the operation is toroidal, the "gaps" between the \$r\$-th row and the 1st row (resp. the \$c\$-th column and the 1st column) must also be filled, which is placed below the original elements of the \$r\$-th row (resp. on the right side of the \$c\$-th column).

You can take \$M\$ and \$n\$ (and optionally \$r\$ and \$c\$) as input and output the resulting matrix in any suitable format. \$n\$ is guaranteed to be a positive integer. The input matrix and the result may have non-integers.

Standard rules apply. The shortest code in bytes wins.

Test cases

# one-element matrix
M = [[1]], n = 3
[[1, 1, 1],
 [1, 1, 1],
 [1, 1, 1]]

# one-element matrix, large n
M = [[1]], n = 100
(100-by-100 matrix of ones)

# one-row matrix
M = [[0, 6, 3, 6]], n = 3
[[0, 2, 4, 6, 5, 4, 3, 4, 5, 6, 4, 2],
 [0, 2, 4, 6, 5, 4, 3, 4, 5, 6, 4, 2],
 [0, 2, 4, 6, 5, 4, 3, 4, 5, 6, 4, 2]]

# one-column matrix
M = [[0], [6], [3], [6]], n = 3
(transpose of the above)

# n = 1
M = [[1, 9, 8, 3],
     [5, 4, 2, 7],
     [3, 8, 5, 1]], n = 1
(same as M)

# 2-by-2 matrix; here the result is rounded to 2 decimal places for convenience.
# An answer doesn't need to round them, though one may choose to do so.
M = [[0, 9],
     [3, 6]], n = 3
[[0, 3,    6,    9, 6,    3],
 [1, 3.33, 5.67, 8, 5.67, 3.33],
 [2, 3.67, 5.33, 7, 5.33, 3.67],
 [3, 4,    5,    6, 5,    4],
 [2, 3.67, 5.33, 7, 5.33, 3.67],
 [1, 3.33, 5.67, 8, 5.67, 3.33]]

# a larger test case
M = [[0, 25, 0],
     [25, 0, 0],
     [0, 0, 25]], n = 5
[[0, 5, 10, 15, 20, 25, 20, 15, 10, 5, 0, 0, 0, 0, 0],
 [5, 8, 11, 14, 17, 20, 16, 12, 8, 4, 0, 1, 2, 3, 4],
 [10, 11, 12, 13, 14, 15, 12, 9, 6, 3, 0, 2, 4, 6, 8],
 [15, 14, 13, 12, 11, 10, 8, 6, 4, 2, 0, 3, 6, 9, 12],
 [20, 17, 14, 11, 8, 5, 4, 3, 2, 1, 0, 4, 8, 12, 16],
 [25, 20, 15, 10, 5, 0, 0, 0, 0, 0, 0, 5, 10, 15, 20],
 [20, 16, 12, 8, 4, 0, 1, 2, 3, 4, 5, 8, 11, 14, 17],
 [15, 12, 9, 6, 3, 0, 2, 4, 6, 8, 10, 11, 12, 13, 14],
 [10, 8, 6, 4, 2, 0, 3, 6, 9, 12, 15, 14, 13, 12, 11],
 [5, 4, 3, 2, 1, 0, 4, 8, 12, 16, 20, 17, 14, 11, 8],
 [0, 0, 0, 0, 0, 0, 5, 10, 15, 20, 25, 20, 15, 10, 5],
 [0, 1, 2, 3, 4, 5, 8, 11, 14, 17, 20, 16, 12, 8, 4],
 [0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 15, 12, 9, 6, 3],
 [0, 3, 6, 9, 12, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2],
 [0, 4, 8, 12, 16, 20, 17, 14, 11, 8, 5, 4, 3, 2, 1]]
\$\endgroup\$
  • \$\begingroup\$ "an answer shouldn't round the values" - shouldn't or doesn't need to? Perhaps specify a minimum acceptable decimal precision? \$\endgroup\$ – Shaggy Jun 15 at 10:09
  • \$\begingroup\$ @Shaggy Doesn't need to, my mistake. Of course any programming language will try to round to some places before printing it. \$\endgroup\$ – Bubbler Jun 15 at 10:12
5
\$\begingroup\$

APL (Dyalog Extended), 27 26 bytes

-1 thanks to Bubbler.

Anonymous infix lambda. Takes \$n\$ as left argument and \$M\$ as right argument.

{⊃+⌿,(⍳⍺)⍉⍤⌽\⍣2⊂⍺/⍺⌿⍵÷⍺*2}

Try it online! (the \$n=100\$ case run out of memory on TIO gives by default, but works offline)

{} "dfn"; is \$n\$ and is \$M\$

⍺*2\$n^2\$

⍵÷\$M\over n^2\$

⍺⌿ replicate vertically so each row becomes \$n\$ copies

⍺/ replicate horizontally so each column becomes \$n\$ copies

 enclose to work on entire matrix

(⍳⍺)⍣2 do the following twice, each time with the \$0,1…n-1\$ as left argument:

  \ outer "product" using the following tacit function instead of multiplication:

    cyclically rotate the rows by the indices

    then:

     transpose

, flatten

+⌿ sum

 disclose (since the summation reduced rank from 1 to 0 by enclosing)

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I guess ⍉⍤⌽ should save a byte? \$\endgroup\$ – Bubbler Jun 15 at 10:46
  • \$\begingroup\$ @Bubbler Yes, thanks. \$\endgroup\$ – Adám Jun 15 at 10:48
  • \$\begingroup\$ "with the 0, 2, ..., n-1 as left argument:" has a typo \$\endgroup\$ – RGS Jun 15 at 11:02
  • \$\begingroup\$ @RGS Yes, thanks. \$\endgroup\$ – Adám Jun 15 at 11:02
4
\$\begingroup\$

J, 22 bytes

(1#.&|:<@[1&|.[#%~)^:2

Try it online!

The "blur" is separable so operate in two passes where each pass operates on the rows and transposes its results.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

R, 97 92 91 86 bytes

function(m,n,`[`=apply)m[1,h][1,h<-function(i)approxfun(c(i,i))(0:(n*sum(1|i)-1)/n+1)]

Try it online!

Thanks to Giuseppe for -5 bytes.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I've never seen approx before. Right tool for the job. You can get down to 92 bytes. \$\endgroup\$ – Giuseppe Jun 15 at 18:04
  • 1
    \$\begingroup\$ Thanks, I was pretty sure there must be something for this in base R, but I actually hoped it would support 2D interpolation at once :) \$\endgroup\$ – Kirill L. Jun 15 at 18:09
1
\$\begingroup\$

Charcoal, 36 bytes

IE×ηLθE×ηL§θ⁰∕ΣEη∕ΣE秧θ÷⁺ινη÷⁺λπηηη

Try it online! Link is to verbose version of code. Explanation:

Cast the final array to string for implicit print (each row's cells print vertically and rows are double-spaced).

E×ηLθ

Loop over each row of the final array.

E×ηL§θ⁰

Loop over each column of the final array.

∕ΣEη∕ΣE秧θ÷⁺ινη÷⁺λπηηη

Extract an n-by-n square from a virtual array created by a simple inflation of the original array, where the top left of the square is at the final row and column. Cyclic indexing ensures that the square wraps around toroidally. The average of the elements is then taken.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Python 2, 109 bytes

M,n=input()
exec"M=[[i%n*((r*2)[i/n+1]-r[i/n])/n+r[i/n]for i in range(len(r)*n)]for r in zip(*M)];"*2
print M

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 63?

I can't remember the rules regarding non-ASCII characters but it looks like they are in play.

ListCorrelate[##/n^2&[n-Abs[n-Range[2n-1]]],Upsample[m,n,n],1]

 is short notation for TensorProduct.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES10), 170 bytes

Takes input as (m)(n).

m=>n=>(T=m=>m.map((r,y)=>r.map((v,x)=>(M[x]=M[x]||[])[y]=v),M=[])&&M)((g=m=>m.map((r,y)=>r.flatMap((v,x)=>[...Array(n)].map((_,i)=>v+(r[-~x%r.length]-v)*i/n))))(T(g(m))))

Try it online! (with formatted outputs for readability)

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.