Exploding NumbersExploded SuffixesMatrix in “slash” orderLet's design a digit mosaicRemove surrounding...
How to not forget my phone in the bathroom?
How can guns be countered by melee combat without raw-ability or exceptional explanations?
Can you wish for more wishes from an Efreeti bound to service via an Efreeti Bottle?
Are encryption algorithms with fixed-point free permutations inherently flawed?
How many copper coins fit inside a cubic foot?
How does the income of your target audience matter for logo design?
How can I portray body horror and still be sensitive to people with disabilities?
Where can I educate myself on D&D universe lore, specifically on vampires and supernatural monsters?
Taking an academic pseudonym?
multiple null checks in Java8
TikZ-Tree with asymmetric siblings
Why don't reads from /dev/zero count as I/O?
Why Third 'Reich'? Why is 'reich' not translated when 'third' is? What is the English synonym of reich?
In a world with multiracial creatures, what word can be used instead of mankind?
STM32 PWM problem
What is formjacking?
80-bit collision resistence because of 80-bit x87 registers?
Boss asked me to sign a resignation paper without a date on it along with my new contract
Ramanujan's radical and how we define an infinite nested radical
Is Apex Sometimes Case Sensitive?
How to play songs that contain one guitar when we have two or more guitarists?
How do I write a maintainable, fast, compile-time bit-mask in C++?
How can a kingdom keep the secret of a missing monarch from the public?
Sing Baby Shark
Exploding Numbers
Exploded SuffixesMatrix in “slash” orderLet's design a digit mosaicRemove surrounding zeroes of a 2d arrayChop off the matrix to get the desired sumOutput the anti-clockwise inward spiral of a 2D arrayTrim that distracting background off!The Hungry MouseMatrix rotation sortBorderless table
$begingroup$
sandbox (deleted)
Lets define a matrix of 9s as:
$$ N = begin{bmatrix} 9&9&9\9&9&9\9&9&9 end{bmatrix} $$
Lets define an exploding number as a number at position $(x,y)$ that can be decomposed into equal integers between all its adjacent neighbors (including itself) and the absolute value of each portion is greater than 0.
From the previous matrix, lets explode the number at position $(1,1)$ (0 indexed)
$$ N = begin{bmatrix} 9&9&9\9&color{red}9&9\9&9&9 end{bmatrix} $$
$$ N = begin{bmatrix} 9+color{red}1&9+color{red}1&9+color{red}1\9+color{red}1&color{blue}0+color{red}1&9+color{red}1\9+color{red}1&9+color{red}1&9+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 10&10&10\10&color{red}1&10\10&10&10 end{bmatrix} $$
Sometimes, decomposing result into a rational number greater than 1. This is something we need to avoid when exploding numbers. In this cases the remainder will be assigned to the exploded number.
To demonstrate it, lets continue working with our previous matrix. This time we will explode the number at position $(0,0)$
$$ N = begin{bmatrix} color{red}{10}&10&10\10&1&10\10&10&10 end{bmatrix} $$
Here we have 3 neightbors and the number itself. Here the equation is something like $10/4$ which give us 2 for each and 2 as remainder.
$$ N = begin{bmatrix} color{blue}2+color{red}{2}&color{red}{10+2}&10\color{red}{10+2}&color{red}{1+2}&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} color{red}{4}&12&10\12&3&10\10&10&10 end{bmatrix} $$
As well, sometimes a number wont be big enough to be decomposed in equal parts (where the abs is greater than 0) between his neighbors (|rational number| < 1). In this cases we need to "borrow" from the exploded number in order to maintain the "greater than 0" condition. Lets continue with our previous example and explode the number at position $(1,1)$.
$$ N = begin{bmatrix} 4&12&10\12&color{red}3&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} 4+color{red}1&12+color{red}1&10+color{red}1\12+color{red}1&color{blue}0+color{red}{1}-color{green}6&10+color{red}1\10+color{red}1&10+color{red}1&10+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 5&13&11\13&color{red}{-5}&11\11&11&11 end{bmatrix} $$
The challenge is, given a list of $(x,y)$ positions and an finite non-empty array of natural numbers, return the exploded form after each number from the positions list has been exploded.
Test cases
Input: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]
Output: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]
Input: Initial matrix: [[9, 8, 7], [8, 9, 7], [8, 7, 9]], numbers: [[0,0],[1,1],[2,2]]
Output: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]
Input: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]
Output: [[-9, 3],[3, 3]]
Input: Initial Matrix: [[10, 20, 30],[30, 20, 10],[40, 50, 60]], numbers: [[0,2],[2,0],[1,1],[1,0]]
Output: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]
Input: Initial Matrix: [[1]], numbers: [[0,0]]
Output: [[1]]
Input: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]
Output: [[1, 1, 4]]
Notes
Input/Output rules apply
You can assume input matrix will never be empty
You can assume coordinates are always going to be valid
Input coord in test cases is given as (row, column). If you need it to be (x, y) you can swap the values. If so, please state that in your answer
code-golf matrix
$endgroup$
add a comment |
$begingroup$
sandbox (deleted)
Lets define a matrix of 9s as:
$$ N = begin{bmatrix} 9&9&9\9&9&9\9&9&9 end{bmatrix} $$
Lets define an exploding number as a number at position $(x,y)$ that can be decomposed into equal integers between all its adjacent neighbors (including itself) and the absolute value of each portion is greater than 0.
From the previous matrix, lets explode the number at position $(1,1)$ (0 indexed)
$$ N = begin{bmatrix} 9&9&9\9&color{red}9&9\9&9&9 end{bmatrix} $$
$$ N = begin{bmatrix} 9+color{red}1&9+color{red}1&9+color{red}1\9+color{red}1&color{blue}0+color{red}1&9+color{red}1\9+color{red}1&9+color{red}1&9+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 10&10&10\10&color{red}1&10\10&10&10 end{bmatrix} $$
Sometimes, decomposing result into a rational number greater than 1. This is something we need to avoid when exploding numbers. In this cases the remainder will be assigned to the exploded number.
To demonstrate it, lets continue working with our previous matrix. This time we will explode the number at position $(0,0)$
$$ N = begin{bmatrix} color{red}{10}&10&10\10&1&10\10&10&10 end{bmatrix} $$
Here we have 3 neightbors and the number itself. Here the equation is something like $10/4$ which give us 2 for each and 2 as remainder.
$$ N = begin{bmatrix} color{blue}2+color{red}{2}&color{red}{10+2}&10\color{red}{10+2}&color{red}{1+2}&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} color{red}{4}&12&10\12&3&10\10&10&10 end{bmatrix} $$
As well, sometimes a number wont be big enough to be decomposed in equal parts (where the abs is greater than 0) between his neighbors (|rational number| < 1). In this cases we need to "borrow" from the exploded number in order to maintain the "greater than 0" condition. Lets continue with our previous example and explode the number at position $(1,1)$.
$$ N = begin{bmatrix} 4&12&10\12&color{red}3&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} 4+color{red}1&12+color{red}1&10+color{red}1\12+color{red}1&color{blue}0+color{red}{1}-color{green}6&10+color{red}1\10+color{red}1&10+color{red}1&10+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 5&13&11\13&color{red}{-5}&11\11&11&11 end{bmatrix} $$
The challenge is, given a list of $(x,y)$ positions and an finite non-empty array of natural numbers, return the exploded form after each number from the positions list has been exploded.
Test cases
Input: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]
Output: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]
Input: Initial matrix: [[9, 8, 7], [8, 9, 7], [8, 7, 9]], numbers: [[0,0],[1,1],[2,2]]
Output: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]
Input: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]
Output: [[-9, 3],[3, 3]]
Input: Initial Matrix: [[10, 20, 30],[30, 20, 10],[40, 50, 60]], numbers: [[0,2],[2,0],[1,1],[1,0]]
Output: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]
Input: Initial Matrix: [[1]], numbers: [[0,0]]
Output: [[1]]
Input: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]
Output: [[1, 1, 4]]
Notes
Input/Output rules apply
You can assume input matrix will never be empty
You can assume coordinates are always going to be valid
Input coord in test cases is given as (row, column). If you need it to be (x, y) you can swap the values. If so, please state that in your answer
code-golf matrix
$endgroup$
$begingroup$
new to code golf; what format is the sample allowed to take these matrices in? Any format that exists in the language? String form exactly as written?
$endgroup$
– rtpax
18 hours ago
1
$begingroup$
I suggest adding a test case for non-square matricies.
$endgroup$
– Οurous
16 hours ago
$begingroup$
@Ourous uh oh, I had been writing my program assuming they were guaranteed to be square, back to the drawing board I guess
$endgroup$
– rtpax
16 hours ago
$begingroup$
Can we assume the matrix-size is at least 2 by 2? Or can a 1 by 1 matrix be input as well?
$endgroup$
– Kevin Cruijssen
3 hours ago
add a comment |
$begingroup$
sandbox (deleted)
Lets define a matrix of 9s as:
$$ N = begin{bmatrix} 9&9&9\9&9&9\9&9&9 end{bmatrix} $$
Lets define an exploding number as a number at position $(x,y)$ that can be decomposed into equal integers between all its adjacent neighbors (including itself) and the absolute value of each portion is greater than 0.
From the previous matrix, lets explode the number at position $(1,1)$ (0 indexed)
$$ N = begin{bmatrix} 9&9&9\9&color{red}9&9\9&9&9 end{bmatrix} $$
$$ N = begin{bmatrix} 9+color{red}1&9+color{red}1&9+color{red}1\9+color{red}1&color{blue}0+color{red}1&9+color{red}1\9+color{red}1&9+color{red}1&9+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 10&10&10\10&color{red}1&10\10&10&10 end{bmatrix} $$
Sometimes, decomposing result into a rational number greater than 1. This is something we need to avoid when exploding numbers. In this cases the remainder will be assigned to the exploded number.
To demonstrate it, lets continue working with our previous matrix. This time we will explode the number at position $(0,0)$
$$ N = begin{bmatrix} color{red}{10}&10&10\10&1&10\10&10&10 end{bmatrix} $$
Here we have 3 neightbors and the number itself. Here the equation is something like $10/4$ which give us 2 for each and 2 as remainder.
$$ N = begin{bmatrix} color{blue}2+color{red}{2}&color{red}{10+2}&10\color{red}{10+2}&color{red}{1+2}&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} color{red}{4}&12&10\12&3&10\10&10&10 end{bmatrix} $$
As well, sometimes a number wont be big enough to be decomposed in equal parts (where the abs is greater than 0) between his neighbors (|rational number| < 1). In this cases we need to "borrow" from the exploded number in order to maintain the "greater than 0" condition. Lets continue with our previous example and explode the number at position $(1,1)$.
$$ N = begin{bmatrix} 4&12&10\12&color{red}3&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} 4+color{red}1&12+color{red}1&10+color{red}1\12+color{red}1&color{blue}0+color{red}{1}-color{green}6&10+color{red}1\10+color{red}1&10+color{red}1&10+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 5&13&11\13&color{red}{-5}&11\11&11&11 end{bmatrix} $$
The challenge is, given a list of $(x,y)$ positions and an finite non-empty array of natural numbers, return the exploded form after each number from the positions list has been exploded.
Test cases
Input: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]
Output: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]
Input: Initial matrix: [[9, 8, 7], [8, 9, 7], [8, 7, 9]], numbers: [[0,0],[1,1],[2,2]]
Output: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]
Input: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]
Output: [[-9, 3],[3, 3]]
Input: Initial Matrix: [[10, 20, 30],[30, 20, 10],[40, 50, 60]], numbers: [[0,2],[2,0],[1,1],[1,0]]
Output: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]
Input: Initial Matrix: [[1]], numbers: [[0,0]]
Output: [[1]]
Input: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]
Output: [[1, 1, 4]]
Notes
Input/Output rules apply
You can assume input matrix will never be empty
You can assume coordinates are always going to be valid
Input coord in test cases is given as (row, column). If you need it to be (x, y) you can swap the values. If so, please state that in your answer
code-golf matrix
$endgroup$
sandbox (deleted)
Lets define a matrix of 9s as:
$$ N = begin{bmatrix} 9&9&9\9&9&9\9&9&9 end{bmatrix} $$
Lets define an exploding number as a number at position $(x,y)$ that can be decomposed into equal integers between all its adjacent neighbors (including itself) and the absolute value of each portion is greater than 0.
From the previous matrix, lets explode the number at position $(1,1)$ (0 indexed)
$$ N = begin{bmatrix} 9&9&9\9&color{red}9&9\9&9&9 end{bmatrix} $$
$$ N = begin{bmatrix} 9+color{red}1&9+color{red}1&9+color{red}1\9+color{red}1&color{blue}0+color{red}1&9+color{red}1\9+color{red}1&9+color{red}1&9+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 10&10&10\10&color{red}1&10\10&10&10 end{bmatrix} $$
Sometimes, decomposing result into a rational number greater than 1. This is something we need to avoid when exploding numbers. In this cases the remainder will be assigned to the exploded number.
To demonstrate it, lets continue working with our previous matrix. This time we will explode the number at position $(0,0)$
$$ N = begin{bmatrix} color{red}{10}&10&10\10&1&10\10&10&10 end{bmatrix} $$
Here we have 3 neightbors and the number itself. Here the equation is something like $10/4$ which give us 2 for each and 2 as remainder.
$$ N = begin{bmatrix} color{blue}2+color{red}{2}&color{red}{10+2}&10\color{red}{10+2}&color{red}{1+2}&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} color{red}{4}&12&10\12&3&10\10&10&10 end{bmatrix} $$
As well, sometimes a number wont be big enough to be decomposed in equal parts (where the abs is greater than 0) between his neighbors (|rational number| < 1). In this cases we need to "borrow" from the exploded number in order to maintain the "greater than 0" condition. Lets continue with our previous example and explode the number at position $(1,1)$.
$$ N = begin{bmatrix} 4&12&10\12&color{red}3&10\10&10&10 end{bmatrix} $$
$$ N = begin{bmatrix} 4+color{red}1&12+color{red}1&10+color{red}1\12+color{red}1&color{blue}0+color{red}{1}-color{green}6&10+color{red}1\10+color{red}1&10+color{red}1&10+color{red}1 end{bmatrix} $$
$$ N = begin{bmatrix} 5&13&11\13&color{red}{-5}&11\11&11&11 end{bmatrix} $$
The challenge is, given a list of $(x,y)$ positions and an finite non-empty array of natural numbers, return the exploded form after each number from the positions list has been exploded.
Test cases
Input: initial matrix: [[3, 3, 3], [3, 3, 3], [3, 3, 3]], numbers: [[0,0],[0,1],[0,2]]
Output: [[1, 0, 1], [5, 6, 5], [3, 3, 3]]
Input: Initial matrix: [[9, 8, 7], [8, 9, 7], [8, 7, 9]], numbers: [[0,0],[1,1],[2,2]]
Output: [[4, 11, 8],[11, 5, 10],[9, 10, 4]]
Input: Initial matrix: [[0, 0], [0, 0]], numbers: [[0,0],[0,0],[0,0]]
Output: [[-9, 3],[3, 3]]
Input: Initial Matrix: [[10, 20, 30],[30, 20, 10],[40, 50, 60]], numbers: [[0,2],[2,0],[1,1],[1,0]]
Output: [[21, 38, 13], [9, 12, 21], [21, 71, 64]]
Input: Initial Matrix: [[1]], numbers: [[0,0]]
Output: [[1]]
Input: Initial Matrix: [[1, 2, 3]], numbers: [[0,0], [0, 1]]
Output: [[1, 1, 4]]
Notes
Input/Output rules apply
You can assume input matrix will never be empty
You can assume coordinates are always going to be valid
Input coord in test cases is given as (row, column). If you need it to be (x, y) you can swap the values. If so, please state that in your answer
code-golf matrix
code-golf matrix
edited 1 hour ago
Luis felipe De jesus Munoz
asked 20 hours ago
Luis felipe De jesus MunozLuis felipe De jesus Munoz
4,84721466
4,84721466
$begingroup$
new to code golf; what format is the sample allowed to take these matrices in? Any format that exists in the language? String form exactly as written?
$endgroup$
– rtpax
18 hours ago
1
$begingroup$
I suggest adding a test case for non-square matricies.
$endgroup$
– Οurous
16 hours ago
$begingroup$
@Ourous uh oh, I had been writing my program assuming they were guaranteed to be square, back to the drawing board I guess
$endgroup$
– rtpax
16 hours ago
$begingroup$
Can we assume the matrix-size is at least 2 by 2? Or can a 1 by 1 matrix be input as well?
$endgroup$
– Kevin Cruijssen
3 hours ago
add a comment |
$begingroup$
new to code golf; what format is the sample allowed to take these matrices in? Any format that exists in the language? String form exactly as written?
$endgroup$
– rtpax
18 hours ago
1
$begingroup$
I suggest adding a test case for non-square matricies.
$endgroup$
– Οurous
16 hours ago
$begingroup$
@Ourous uh oh, I had been writing my program assuming they were guaranteed to be square, back to the drawing board I guess
$endgroup$
– rtpax
16 hours ago
$begingroup$
Can we assume the matrix-size is at least 2 by 2? Or can a 1 by 1 matrix be input as well?
$endgroup$
– Kevin Cruijssen
3 hours ago
$begingroup$
new to code golf; what format is the sample allowed to take these matrices in? Any format that exists in the language? String form exactly as written?
$endgroup$
– rtpax
18 hours ago
$begingroup$
new to code golf; what format is the sample allowed to take these matrices in? Any format that exists in the language? String form exactly as written?
$endgroup$
– rtpax
18 hours ago
1
1
$begingroup$
I suggest adding a test case for non-square matricies.
$endgroup$
– Οurous
16 hours ago
$begingroup$
I suggest adding a test case for non-square matricies.
$endgroup$
– Οurous
16 hours ago
$begingroup$
@Ourous uh oh, I had been writing my program assuming they were guaranteed to be square, back to the drawing board I guess
$endgroup$
– rtpax
16 hours ago
$begingroup$
@Ourous uh oh, I had been writing my program assuming they were guaranteed to be square, back to the drawing board I guess
$endgroup$
– rtpax
16 hours ago
$begingroup$
Can we assume the matrix-size is at least 2 by 2? Or can a 1 by 1 matrix be input as well?
$endgroup$
– Kevin Cruijssen
3 hours ago
$begingroup$
Can we assume the matrix-size is at least 2 by 2? Or can a 1 by 1 matrix be input as well?
$endgroup$
– Kevin Cruijssen
3 hours ago
add a comment |
7 Answers
7
active
oldest
votes
$begingroup$
C(GCC) 220 216 214 212 bytes
credit to @ceilingcat for 2 bytes
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R,int C,int*m){for(int*i=m+R*C;~*i;) {int*M,l=*i+++C**i++,a=0,b;L(r)L(c)P?:++a;M=m+l;b=*M/a;b+=!b;*M- =b*a;L(r)L(c)M[r*C+c]+=P?0:b;}}
Run it here
a slightly less golfed version
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R, int C, int*m) {
for(int*i=m+R*C;~*i;) {
int*M,l=*i+++C**i++,a=0,b;
L(r)
L(c)
P?:++a;
M=m+l;
b=*M/a;
b+=!b;
*M-=b*a;
L(r)
L(c)
M[r*C+c]+=P?0:b;
}
}
The calling code with an example
int main()
{
int matrix[] = {3,3,3,3,3,3,3,3,3,0,0,0,1,0,2,-1};
int rows = 3;
int columns = 3;
f(rows,columns,matrix);
for(int r = 0; r < rows; ++r) {
for(int c = 0; c < columns; ++c) {
printf("%03d,",matrix[r*columns + c]);
}
printf("n");
}
}
and the output
001,005,003,
000,006,003,
001,005,003,
New contributor
$endgroup$
9
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
1
$begingroup$
SuggestM[r*C+c]
instead of*(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
add a comment |
$begingroup$
JavaScript (ES7), 126 125 123 121 bytes
Saved 2 bytes thanks to @Shaggy
Takes input as (matrix)(list)
. Outputs by modifying the matrix.
m=>a=>a.map(([Y,X])=>(g=n=>m[m.map((r,y)=>r.map((_,x)=>(x-X)**2+(y-Y)**2<3&&r[n++,x]++)),(m[Y][X]+=~n)<n||g``,Y][X]++)``)
Try it online!
How?
If we were to strictly follow the algorithm described in the challenge, we'd have to perform the following operations for each position pair $(x,y)$:
- walk through the matrix to compute the number of neighbors $n$
- compute $lfloor m(x,y) / nrfloor$ and deduce the quantity $q$ that needs to be added to each neighbor
- walk through the matrix again to update each neighbor
- update $m(x,y)$
Instead of that, we use a recursive function which executes a simpler flow of operations, repeated as many times as needed:
- for each neighbor and for the reference cell itself: increment the cell and increment a counter $n$ (initialized to $0$)
- subtract $n+1$ from the reference cell
- if the above result is greater than or equal to $n$, do a recursive call
- increment the reference cell (all steps of this kind are executed in succession when the last recursive call has completed)
The main benefit is that we only need one loop over the matrix. The second benefit is that we don't have to compute any quotient at all.
Example
$$M=begin{pmatrix}
0&0&0\
0&26&0\
0&0&0
end{pmatrix}text{ and }(x,y)=(1,1)$$
After step 1 of the first iteration, we have:
$$M=begin{pmatrix}
1&1&1\
1&27&1\
1&1&1
end{pmatrix}text{ and }n=9$$
And after step 2 of the first iteration:
$$M=begin{pmatrix}
1&1&1\
1&17&1\
1&1&1
end{pmatrix}$$
The key point here is that the reference cell is updated by taking only the cost ($-9$) into account without the gain ($+1$), so that we know how much we can still draw from it.
Consequently, the sum of the cells is no longer equal to $26$ at this point. But this will be corrected at the end of the process, where all gains on the reference cell are accounted at once.
Step 3 of the first iteration: because $17$ is greater than $9$, we do a recursive call.
After step 1 of the second iteration, we have:
$$M=begin{pmatrix}
2&2&2\
2&18&2\
2&2&2
end{pmatrix}text{ and }n=9$$
And after step 2 of the second iteration:
$$M=begin{pmatrix}
2&2&2\
2&8&2\
2&2&2
end{pmatrix}$$
Step 3 of the second iteration: this time, we have $8<9$, so we stop there.
We now increment the reference cell twice (step 4 of both iterations), leading to the final result:
$$M=begin{pmatrix}
2&2&2\
2&10&2\
2&2&2
end{pmatrix}$$
Commented
m => a => // m[] = input matrix, a[] = list of positions
a.map(([Y, X]) => ( // for each pair (X, Y) in a[]:
g = n => // g = recursive function expecting n = 0
m[ //
m.map((r, y) => // for each row r[] at position y in m[]:
r.map((_, x) => // for each value at position x in r[]:
(x - X) ** 2 + // if the quadrance between (x, y)
(y - Y) ** 2 < 3 // and (X, Y) is less than 3:
&& r[n++, x]++ // increment n and increment r[x]
) // end
), // end
(m[Y][X] += ~n) // subtract n + 1 from m[Y][X]
< n // if the result is greater than or equal to n:
|| g``, // do a recursive call
Y //
][X]++ // increment m[Y][X]
)`` // initial call to g
) // end
$endgroup$
1
$begingroup$
You can save a couple of bytes by replacing both occurrences of(0)
with 2 backticks.
$endgroup$
– Shaggy
3 hours ago
add a comment |
$begingroup$
Clean, 181 167 bytes
import StdEnv;
foldlm(x,y)={{if(d>2)0b+e-if(d>0)0b*n\e<-:l&v<-[0..],let{b=max m.[y,x]n/n;$a b=2+sign a-(a+1)/size b;n= $x l* $y m;d=(v-x)^2+(u-y)^2}}\l<-:m&u<-[0..]}
Try it online!
In the form of a partially-applied function literal.
Expanded (first version):
f // functinon f on {{Int}} and [(Int,Int)]
= foldl m (x, y) // fold :: (a -> b -> a) a [b] -> a with first argument {{Int}} (Int,Int) -> {{Int}} giving {{Int}} [(Int,Int)] -> {{Int}}
= { // an array of
{ // arrays of
if(d > 2) 0 b // the amount we give to the neighbors
+ e // plus the current entry
- if(d > 0) 0 b // minus the amount taken from the target entry
* n // times the number of neighbors, if we're on the target
\ // for each
e <-: l // element of row l
& v <- [0..] // and x-index v
, let // local definitions:
b // the amount given to the neighbors
= max // we need at least 1 each, so take the largest of
m.[y, x] // the target entry
n // or the number of neighbors
/ n // divide it by the number of neighbors
n // the number of neighbors
= ( // sum of
1 // one
+ s x // if x is at the left edge = 0 else 1
+ s ( // if x is at the right edge = 0 else 1
size l
- x
- 1
)
) * ( // times the sum of
1 // one
+ s y // if y is at the top edge = 0 else 1
+ s ( // if y is at the bottom edge = 0 else 1
size m
- y
- 1
)
)
d // distance from the target point
= (v - x)^2
+ (u - y)^2
}
\ // for each
l <-: m // row l in matrix m
& u <- [0..] // and y-index u
}
$endgroup$
add a comment |
$begingroup$
Rust - 295 bytes
fn explode(p:(i8,i8),v:&mut Vec<Vec<i8>>){let x=v[p.0 as usize][p.1 as usize];let q=|x,y|x*x+y*y;loop{let mut t=0;for i in 0..v.len(){for j in 0..v[i].len(){if q(i as i8-p.0,j as i8-p.1)<3{v[i][j]+=1;v[p.0 as usize][p.1 as usize]-=1;t+=1;}}}if v[p.0 as usize][p.1 as usize]<=(x/t+x%t){break;}}}
This is pretty long due to Rust requiring unsigned integer indexing of vectors, but requiring signed integers to do subtraction resulting in negatives. However I believe my algorithm is the "shortest algorithm" so far. There is actually no need to deal with detecting edges, bottom, etc.
Notice three things: One, the sum of all cells is always constant. Two, this is a division / remainder situation, so we can apply Bresenham-algorithm style thinking. Three, the question always adds the same number to all cells within a certain distance of the special position cell, before dealing with the "extra" stuff in the special position.
Algorithm:
Store original value of cell at position P into M.
Begin Loop:
Iterate over each cell I in the matrix. If the position of cell I is within 3 Quadrance (squared distance) of the position P, then subtract 1 from cell P and add 1 to the cell I. Count how many times this is done in one iteration through the matrix.
If the value leftover in the cell at position P is less than or equal to M / Count + M modulo Count, then break the loop. Otherwise perform the loop again.
The resulting matrix will be the exploded version. Count is basically a way to count neighbors without dealing with edges. Looping is a way to break down the division/addition stuff into a repeated single addition/subtraction of one. The modulo check ensures we will have appropriate remainder left at position P to deal with 'explosions' that are not evenly divisible amongst neighbors. The do/while loop structure allows P<0 to work properly.
Ungolfed version on the Rust Playground
$endgroup$
$begingroup$
Such a long function name isn't necessary, any 1-byter such asf
would do. But you could probably save even more bytes, by using an anonymous function:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
add a comment |
$begingroup$
R, 163 162 161 159 bytes
function(m,l){for(e in l){i=e[1];j=e[2];x=-1:1+i;y=-1:1+j;s=m[x<-x[x<=dim(m)],y<-y[y<=ncol(m)]];z=sum(1|s);d=max(1,m[i,j]%/%z);m[x,y]=s+d;m[i,j]=m[i,j]-d*z};m}
Try it online!
Explanation
function(m,l) { # Take input as matrix m and 1-indexed list of explosion points l
for(e in l) { # Loop over the list of explosion points
i=e[1]; j=e[2] # Assign current coordinates to (i,j) for brevity
x=-1:1+i # Assign the ranges of neighboring cells: (i-1) to (i+1),
y=-1:1+j # and (j-1) to (j+1)
s= # Take the submatrix s=m[x,y]
m[x<-x[x<=dim(m)] # But first trim x and y from above to prevent out of bounds errors,
,y<-y[y<=ncol(m)]] # trimming from below isn't necessary, as R tolerates index 0
z=sum(1|s) # Count the neighbors
d=max(1,m[i,j]%/%z) # Estimate, how much we'll distribute to each neighbor
m[x,y]=s+d # Add the distributed amount to each cell of the submatrix
m[i,j]=m[i,j]-d*z # Subtract the total amount from the exploded cell
}
m # Return the modified matrix
}
$endgroup$
add a comment |
$begingroup$
Common Lisp, 498 bytes
(defmacro s(l c x)`(incf(aref m,l,c),x))
(defmacro w(a &rest f)`(if(,a(or(= l 0)(= l(d 0)))(or(= c 0)(= c(d 1)))),@f))
(defmacro d(n)`(1-(array-dimension m,n)))
(defmacro p(i l m &rest f)`(loop for,i from(1-,l)to(1+,l)when(and(>=,i 0)(<=,i,m))do,@f))
(defmacro g()`(or(p i l(d 0)(p j c(d 1)(s i j 1)))(s l c(- v))))
(defun f(m l c)(let((v(w and 4(w or 6 9))))(if (<(/(s l c 0)v)1)(g)(loop for i to(1-(/(s l c 0)v))do(g)))))
(defun c(m n)(dotimes(i(length n))(f m(nth 0(nth i n))(nth 1(nth i n))))m)
Try it online!
Use this function as (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
Better readable version:
(defmacro s (l c x)
`(incf (aref m ,l ,c) ,x))
(defmacro w (a &rest f)
`(if (,a (or (= l 0)
(= l (d 0)))
(or (= c 0)
(= c (d 1))))
,@f))
(defmacro d (n)
`(1- (array-dimension m ,n)))
(defmacro p (i l m &rest f)
`(loop for ,i from (1- ,l) to (1+ ,l)
when (and (>= ,i 0) (<= ,i ,m))
do ,@f))
(defmacro g ()
`(or(p i l (d 0)
(p j c (d 1)
(s i j 1)))
(s l c (- v))))
(defun f (m l c)
(let ((v (w and 4 (w or 6 9))))
(if (< (/ (s l c 0) v) 1)
(g)
(loop for i to (1- (/ (s l c 0) v))
do (g)))))
(defun c (m n)
(dotimes (i (length n))
(f m (nth 0 (nth i n))
(nth 1 (nth i n))))
m)
Output example:
(print (c #2A((3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3)) '((5 0)(4 1)(0 2))))
;; #2A((3 4 0) (3 4 4) (3 3 3) (4 4 4) (5 -4 4) (1 5 4))
(print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
; #2A((1 0 1) (5 6 5) (3 3 3)) => #2A((1 0 1) (5 6 5) (3 3 3))
(print (c #2A((9 8 7) (8 9 7) (8 7 9)) '((0 0)(1 1)(2 2))))
;; #2A((4 11 8) (11 5 10) (9 10 4)) => #2A((4 11 8) (11 5 10) (9 10 4))
(print (c #2A((0 0) (0 0)) '((0 0)(0 0)(0 0))))
;; #2A((-9 3) (3 3)) => #2A((-9 3) (3 3))
(print (c #2A((10 20 30)(30 20 10)(40 50 60)) '((0 2)(2 0)(1 1)(1 0))))
;; #2A((21 38 13) (9 12 21) (21 71 64)) => #2A((21 38 13) (9 12 21) (21 71 64))
New contributor
$endgroup$
add a comment |
$begingroup$
Java 10, 194 193 bytes
M->C->{for(var q:C){int f=1,n=0,X=q[0],Y=q[1],x,y,c=1,t;for(;f>0;f=(M[X][Y]+=~n)<n?0:c++)for(n=0,x=M.length;x-->0;)for(y=M[x].length;y-->0;)if((t=x-X)*t+(t=y-Y)*t<3)M[x][y]+=++n/n;M[X][Y]+=c;}}
Iterative port of @Arnauld's JavaScript answer.
Modifies the input-matrix instead of returning a new one to save bytes.
Try it online.
Explanation:
M->C->{ // Method with two integer-matrix parameters and no return-type
for(var q:C){ // Loop over the coordinates:
int f=1, // Flag integer, starting at 1 for every coordinate
n=0, // Count integer, starting at 0 for every coordinate
X=q[0],Y=q[1], // The current X,Y coordinate
x,y, // Temp x,y coordinates
c=1, // Counter, starting at 1
t; // Temp integer
for(;f>0 // Loop as long as the flag is not 0:
; // After every iteration:
f=(M[X][Y]+=~n) // Decrease the value at X,Y by n+1
<n? // If it's now smaller than the count `n`
0 // Change the flag to 0
: // Else:
c++) // Change the flag to counter `c`, and increase `c` by 1
for(n=0, // Reset the count `n` to 0
x=M.length;x-->0;)// Loop `x` over the rows:
for(y=M[x].length;y-->0;)
// Inner loop `y` over the columns:
if((t=x-X)*t // If the difference between `x` and `X` squared
+(t=y-Y)*t // and the difference between `y` and `Y` squared together
<3){ // Is smaller than 3:
M[x][y]+=++n/n; // Increase count `n` and the value at x,y both by 1
M[X][Y]+=c;}} // Increase the value at X,Y with counter `c`
$endgroup$
1
$begingroup$
Is thetry/catch
really required?
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
1
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), butm[y][x]
with $y$ out of bounds would crash as well.
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand whyundefined[x]
would fail. Anyway, your(x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.
$endgroup$
– Kevin Cruijssen
1 hour ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "200"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f180188%2fexploding-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
C(GCC) 220 216 214 212 bytes
credit to @ceilingcat for 2 bytes
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R,int C,int*m){for(int*i=m+R*C;~*i;) {int*M,l=*i+++C**i++,a=0,b;L(r)L(c)P?:++a;M=m+l;b=*M/a;b+=!b;*M- =b*a;L(r)L(c)M[r*C+c]+=P?0:b;}}
Run it here
a slightly less golfed version
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R, int C, int*m) {
for(int*i=m+R*C;~*i;) {
int*M,l=*i+++C**i++,a=0,b;
L(r)
L(c)
P?:++a;
M=m+l;
b=*M/a;
b+=!b;
*M-=b*a;
L(r)
L(c)
M[r*C+c]+=P?0:b;
}
}
The calling code with an example
int main()
{
int matrix[] = {3,3,3,3,3,3,3,3,3,0,0,0,1,0,2,-1};
int rows = 3;
int columns = 3;
f(rows,columns,matrix);
for(int r = 0; r < rows; ++r) {
for(int c = 0; c < columns; ++c) {
printf("%03d,",matrix[r*columns + c]);
}
printf("n");
}
}
and the output
001,005,003,
000,006,003,
001,005,003,
New contributor
$endgroup$
9
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
1
$begingroup$
SuggestM[r*C+c]
instead of*(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
add a comment |
$begingroup$
C(GCC) 220 216 214 212 bytes
credit to @ceilingcat for 2 bytes
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R,int C,int*m){for(int*i=m+R*C;~*i;) {int*M,l=*i+++C**i++,a=0,b;L(r)L(c)P?:++a;M=m+l;b=*M/a;b+=!b;*M- =b*a;L(r)L(c)M[r*C+c]+=P?0:b;}}
Run it here
a slightly less golfed version
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R, int C, int*m) {
for(int*i=m+R*C;~*i;) {
int*M,l=*i+++C**i++,a=0,b;
L(r)
L(c)
P?:++a;
M=m+l;
b=*M/a;
b+=!b;
*M-=b*a;
L(r)
L(c)
M[r*C+c]+=P?0:b;
}
}
The calling code with an example
int main()
{
int matrix[] = {3,3,3,3,3,3,3,3,3,0,0,0,1,0,2,-1};
int rows = 3;
int columns = 3;
f(rows,columns,matrix);
for(int r = 0; r < rows; ++r) {
for(int c = 0; c < columns; ++c) {
printf("%03d,",matrix[r*columns + c]);
}
printf("n");
}
}
and the output
001,005,003,
000,006,003,
001,005,003,
New contributor
$endgroup$
9
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
1
$begingroup$
SuggestM[r*C+c]
instead of*(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
add a comment |
$begingroup$
C(GCC) 220 216 214 212 bytes
credit to @ceilingcat for 2 bytes
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R,int C,int*m){for(int*i=m+R*C;~*i;) {int*M,l=*i+++C**i++,a=0,b;L(r)L(c)P?:++a;M=m+l;b=*M/a;b+=!b;*M- =b*a;L(r)L(c)M[r*C+c]+=P?0:b;}}
Run it here
a slightly less golfed version
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R, int C, int*m) {
for(int*i=m+R*C;~*i;) {
int*M,l=*i+++C**i++,a=0,b;
L(r)
L(c)
P?:++a;
M=m+l;
b=*M/a;
b+=!b;
*M-=b*a;
L(r)
L(c)
M[r*C+c]+=P?0:b;
}
}
The calling code with an example
int main()
{
int matrix[] = {3,3,3,3,3,3,3,3,3,0,0,0,1,0,2,-1};
int rows = 3;
int columns = 3;
f(rows,columns,matrix);
for(int r = 0; r < rows; ++r) {
for(int c = 0; c < columns; ++c) {
printf("%03d,",matrix[r*columns + c]);
}
printf("n");
}
}
and the output
001,005,003,
000,006,003,
001,005,003,
New contributor
$endgroup$
C(GCC) 220 216 214 212 bytes
credit to @ceilingcat for 2 bytes
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R,int C,int*m){for(int*i=m+R*C;~*i;) {int*M,l=*i+++C**i++,a=0,b;L(r)L(c)P?:++a;M=m+l;b=*M/a;b+=!b;*M- =b*a;L(r)L(c)M[r*C+c]+=P?0:b;}}
Run it here
a slightly less golfed version
#define L(v)for(int v=2;~v--;)
#define P l/C+r<0|l/C+r>=R|l%C+c<0|l%C+c>=C
f(int R, int C, int*m) {
for(int*i=m+R*C;~*i;) {
int*M,l=*i+++C**i++,a=0,b;
L(r)
L(c)
P?:++a;
M=m+l;
b=*M/a;
b+=!b;
*M-=b*a;
L(r)
L(c)
M[r*C+c]+=P?0:b;
}
}
The calling code with an example
int main()
{
int matrix[] = {3,3,3,3,3,3,3,3,3,0,0,0,1,0,2,-1};
int rows = 3;
int columns = 3;
f(rows,columns,matrix);
for(int r = 0; r < rows; ++r) {
for(int c = 0; c < columns; ++c) {
printf("%03d,",matrix[r*columns + c]);
}
printf("n");
}
}
and the output
001,005,003,
000,006,003,
001,005,003,
New contributor
edited 14 mins ago
New contributor
answered 15 hours ago
rtpaxrtpax
1713
1713
New contributor
New contributor
9
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
1
$begingroup$
SuggestM[r*C+c]
instead of*(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
add a comment |
9
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
1
$begingroup$
SuggestM[r*C+c]
instead of*(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
9
9
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
$begingroup$
Welcome to PPCG :)
$endgroup$
– Shaggy
15 hours ago
1
1
$begingroup$
Suggest
M[r*C+c]
instead of *(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
$begingroup$
Suggest
M[r*C+c]
instead of *(M+r*C+c)
$endgroup$
– ceilingcat
3 hours ago
add a comment |
$begingroup$
JavaScript (ES7), 126 125 123 121 bytes
Saved 2 bytes thanks to @Shaggy
Takes input as (matrix)(list)
. Outputs by modifying the matrix.
m=>a=>a.map(([Y,X])=>(g=n=>m[m.map((r,y)=>r.map((_,x)=>(x-X)**2+(y-Y)**2<3&&r[n++,x]++)),(m[Y][X]+=~n)<n||g``,Y][X]++)``)
Try it online!
How?
If we were to strictly follow the algorithm described in the challenge, we'd have to perform the following operations for each position pair $(x,y)$:
- walk through the matrix to compute the number of neighbors $n$
- compute $lfloor m(x,y) / nrfloor$ and deduce the quantity $q$ that needs to be added to each neighbor
- walk through the matrix again to update each neighbor
- update $m(x,y)$
Instead of that, we use a recursive function which executes a simpler flow of operations, repeated as many times as needed:
- for each neighbor and for the reference cell itself: increment the cell and increment a counter $n$ (initialized to $0$)
- subtract $n+1$ from the reference cell
- if the above result is greater than or equal to $n$, do a recursive call
- increment the reference cell (all steps of this kind are executed in succession when the last recursive call has completed)
The main benefit is that we only need one loop over the matrix. The second benefit is that we don't have to compute any quotient at all.
Example
$$M=begin{pmatrix}
0&0&0\
0&26&0\
0&0&0
end{pmatrix}text{ and }(x,y)=(1,1)$$
After step 1 of the first iteration, we have:
$$M=begin{pmatrix}
1&1&1\
1&27&1\
1&1&1
end{pmatrix}text{ and }n=9$$
And after step 2 of the first iteration:
$$M=begin{pmatrix}
1&1&1\
1&17&1\
1&1&1
end{pmatrix}$$
The key point here is that the reference cell is updated by taking only the cost ($-9$) into account without the gain ($+1$), so that we know how much we can still draw from it.
Consequently, the sum of the cells is no longer equal to $26$ at this point. But this will be corrected at the end of the process, where all gains on the reference cell are accounted at once.
Step 3 of the first iteration: because $17$ is greater than $9$, we do a recursive call.
After step 1 of the second iteration, we have:
$$M=begin{pmatrix}
2&2&2\
2&18&2\
2&2&2
end{pmatrix}text{ and }n=9$$
And after step 2 of the second iteration:
$$M=begin{pmatrix}
2&2&2\
2&8&2\
2&2&2
end{pmatrix}$$
Step 3 of the second iteration: this time, we have $8<9$, so we stop there.
We now increment the reference cell twice (step 4 of both iterations), leading to the final result:
$$M=begin{pmatrix}
2&2&2\
2&10&2\
2&2&2
end{pmatrix}$$
Commented
m => a => // m[] = input matrix, a[] = list of positions
a.map(([Y, X]) => ( // for each pair (X, Y) in a[]:
g = n => // g = recursive function expecting n = 0
m[ //
m.map((r, y) => // for each row r[] at position y in m[]:
r.map((_, x) => // for each value at position x in r[]:
(x - X) ** 2 + // if the quadrance between (x, y)
(y - Y) ** 2 < 3 // and (X, Y) is less than 3:
&& r[n++, x]++ // increment n and increment r[x]
) // end
), // end
(m[Y][X] += ~n) // subtract n + 1 from m[Y][X]
< n // if the result is greater than or equal to n:
|| g``, // do a recursive call
Y //
][X]++ // increment m[Y][X]
)`` // initial call to g
) // end
$endgroup$
1
$begingroup$
You can save a couple of bytes by replacing both occurrences of(0)
with 2 backticks.
$endgroup$
– Shaggy
3 hours ago
add a comment |
$begingroup$
JavaScript (ES7), 126 125 123 121 bytes
Saved 2 bytes thanks to @Shaggy
Takes input as (matrix)(list)
. Outputs by modifying the matrix.
m=>a=>a.map(([Y,X])=>(g=n=>m[m.map((r,y)=>r.map((_,x)=>(x-X)**2+(y-Y)**2<3&&r[n++,x]++)),(m[Y][X]+=~n)<n||g``,Y][X]++)``)
Try it online!
How?
If we were to strictly follow the algorithm described in the challenge, we'd have to perform the following operations for each position pair $(x,y)$:
- walk through the matrix to compute the number of neighbors $n$
- compute $lfloor m(x,y) / nrfloor$ and deduce the quantity $q$ that needs to be added to each neighbor
- walk through the matrix again to update each neighbor
- update $m(x,y)$
Instead of that, we use a recursive function which executes a simpler flow of operations, repeated as many times as needed:
- for each neighbor and for the reference cell itself: increment the cell and increment a counter $n$ (initialized to $0$)
- subtract $n+1$ from the reference cell
- if the above result is greater than or equal to $n$, do a recursive call
- increment the reference cell (all steps of this kind are executed in succession when the last recursive call has completed)
The main benefit is that we only need one loop over the matrix. The second benefit is that we don't have to compute any quotient at all.
Example
$$M=begin{pmatrix}
0&0&0\
0&26&0\
0&0&0
end{pmatrix}text{ and }(x,y)=(1,1)$$
After step 1 of the first iteration, we have:
$$M=begin{pmatrix}
1&1&1\
1&27&1\
1&1&1
end{pmatrix}text{ and }n=9$$
And after step 2 of the first iteration:
$$M=begin{pmatrix}
1&1&1\
1&17&1\
1&1&1
end{pmatrix}$$
The key point here is that the reference cell is updated by taking only the cost ($-9$) into account without the gain ($+1$), so that we know how much we can still draw from it.
Consequently, the sum of the cells is no longer equal to $26$ at this point. But this will be corrected at the end of the process, where all gains on the reference cell are accounted at once.
Step 3 of the first iteration: because $17$ is greater than $9$, we do a recursive call.
After step 1 of the second iteration, we have:
$$M=begin{pmatrix}
2&2&2\
2&18&2\
2&2&2
end{pmatrix}text{ and }n=9$$
And after step 2 of the second iteration:
$$M=begin{pmatrix}
2&2&2\
2&8&2\
2&2&2
end{pmatrix}$$
Step 3 of the second iteration: this time, we have $8<9$, so we stop there.
We now increment the reference cell twice (step 4 of both iterations), leading to the final result:
$$M=begin{pmatrix}
2&2&2\
2&10&2\
2&2&2
end{pmatrix}$$
Commented
m => a => // m[] = input matrix, a[] = list of positions
a.map(([Y, X]) => ( // for each pair (X, Y) in a[]:
g = n => // g = recursive function expecting n = 0
m[ //
m.map((r, y) => // for each row r[] at position y in m[]:
r.map((_, x) => // for each value at position x in r[]:
(x - X) ** 2 + // if the quadrance between (x, y)
(y - Y) ** 2 < 3 // and (X, Y) is less than 3:
&& r[n++, x]++ // increment n and increment r[x]
) // end
), // end
(m[Y][X] += ~n) // subtract n + 1 from m[Y][X]
< n // if the result is greater than or equal to n:
|| g``, // do a recursive call
Y //
][X]++ // increment m[Y][X]
)`` // initial call to g
) // end
$endgroup$
1
$begingroup$
You can save a couple of bytes by replacing both occurrences of(0)
with 2 backticks.
$endgroup$
– Shaggy
3 hours ago
add a comment |
$begingroup$
JavaScript (ES7), 126 125 123 121 bytes
Saved 2 bytes thanks to @Shaggy
Takes input as (matrix)(list)
. Outputs by modifying the matrix.
m=>a=>a.map(([Y,X])=>(g=n=>m[m.map((r,y)=>r.map((_,x)=>(x-X)**2+(y-Y)**2<3&&r[n++,x]++)),(m[Y][X]+=~n)<n||g``,Y][X]++)``)
Try it online!
How?
If we were to strictly follow the algorithm described in the challenge, we'd have to perform the following operations for each position pair $(x,y)$:
- walk through the matrix to compute the number of neighbors $n$
- compute $lfloor m(x,y) / nrfloor$ and deduce the quantity $q$ that needs to be added to each neighbor
- walk through the matrix again to update each neighbor
- update $m(x,y)$
Instead of that, we use a recursive function which executes a simpler flow of operations, repeated as many times as needed:
- for each neighbor and for the reference cell itself: increment the cell and increment a counter $n$ (initialized to $0$)
- subtract $n+1$ from the reference cell
- if the above result is greater than or equal to $n$, do a recursive call
- increment the reference cell (all steps of this kind are executed in succession when the last recursive call has completed)
The main benefit is that we only need one loop over the matrix. The second benefit is that we don't have to compute any quotient at all.
Example
$$M=begin{pmatrix}
0&0&0\
0&26&0\
0&0&0
end{pmatrix}text{ and }(x,y)=(1,1)$$
After step 1 of the first iteration, we have:
$$M=begin{pmatrix}
1&1&1\
1&27&1\
1&1&1
end{pmatrix}text{ and }n=9$$
And after step 2 of the first iteration:
$$M=begin{pmatrix}
1&1&1\
1&17&1\
1&1&1
end{pmatrix}$$
The key point here is that the reference cell is updated by taking only the cost ($-9$) into account without the gain ($+1$), so that we know how much we can still draw from it.
Consequently, the sum of the cells is no longer equal to $26$ at this point. But this will be corrected at the end of the process, where all gains on the reference cell are accounted at once.
Step 3 of the first iteration: because $17$ is greater than $9$, we do a recursive call.
After step 1 of the second iteration, we have:
$$M=begin{pmatrix}
2&2&2\
2&18&2\
2&2&2
end{pmatrix}text{ and }n=9$$
And after step 2 of the second iteration:
$$M=begin{pmatrix}
2&2&2\
2&8&2\
2&2&2
end{pmatrix}$$
Step 3 of the second iteration: this time, we have $8<9$, so we stop there.
We now increment the reference cell twice (step 4 of both iterations), leading to the final result:
$$M=begin{pmatrix}
2&2&2\
2&10&2\
2&2&2
end{pmatrix}$$
Commented
m => a => // m[] = input matrix, a[] = list of positions
a.map(([Y, X]) => ( // for each pair (X, Y) in a[]:
g = n => // g = recursive function expecting n = 0
m[ //
m.map((r, y) => // for each row r[] at position y in m[]:
r.map((_, x) => // for each value at position x in r[]:
(x - X) ** 2 + // if the quadrance between (x, y)
(y - Y) ** 2 < 3 // and (X, Y) is less than 3:
&& r[n++, x]++ // increment n and increment r[x]
) // end
), // end
(m[Y][X] += ~n) // subtract n + 1 from m[Y][X]
< n // if the result is greater than or equal to n:
|| g``, // do a recursive call
Y //
][X]++ // increment m[Y][X]
)`` // initial call to g
) // end
$endgroup$
JavaScript (ES7), 126 125 123 121 bytes
Saved 2 bytes thanks to @Shaggy
Takes input as (matrix)(list)
. Outputs by modifying the matrix.
m=>a=>a.map(([Y,X])=>(g=n=>m[m.map((r,y)=>r.map((_,x)=>(x-X)**2+(y-Y)**2<3&&r[n++,x]++)),(m[Y][X]+=~n)<n||g``,Y][X]++)``)
Try it online!
How?
If we were to strictly follow the algorithm described in the challenge, we'd have to perform the following operations for each position pair $(x,y)$:
- walk through the matrix to compute the number of neighbors $n$
- compute $lfloor m(x,y) / nrfloor$ and deduce the quantity $q$ that needs to be added to each neighbor
- walk through the matrix again to update each neighbor
- update $m(x,y)$
Instead of that, we use a recursive function which executes a simpler flow of operations, repeated as many times as needed:
- for each neighbor and for the reference cell itself: increment the cell and increment a counter $n$ (initialized to $0$)
- subtract $n+1$ from the reference cell
- if the above result is greater than or equal to $n$, do a recursive call
- increment the reference cell (all steps of this kind are executed in succession when the last recursive call has completed)
The main benefit is that we only need one loop over the matrix. The second benefit is that we don't have to compute any quotient at all.
Example
$$M=begin{pmatrix}
0&0&0\
0&26&0\
0&0&0
end{pmatrix}text{ and }(x,y)=(1,1)$$
After step 1 of the first iteration, we have:
$$M=begin{pmatrix}
1&1&1\
1&27&1\
1&1&1
end{pmatrix}text{ and }n=9$$
And after step 2 of the first iteration:
$$M=begin{pmatrix}
1&1&1\
1&17&1\
1&1&1
end{pmatrix}$$
The key point here is that the reference cell is updated by taking only the cost ($-9$) into account without the gain ($+1$), so that we know how much we can still draw from it.
Consequently, the sum of the cells is no longer equal to $26$ at this point. But this will be corrected at the end of the process, where all gains on the reference cell are accounted at once.
Step 3 of the first iteration: because $17$ is greater than $9$, we do a recursive call.
After step 1 of the second iteration, we have:
$$M=begin{pmatrix}
2&2&2\
2&18&2\
2&2&2
end{pmatrix}text{ and }n=9$$
And after step 2 of the second iteration:
$$M=begin{pmatrix}
2&2&2\
2&8&2\
2&2&2
end{pmatrix}$$
Step 3 of the second iteration: this time, we have $8<9$, so we stop there.
We now increment the reference cell twice (step 4 of both iterations), leading to the final result:
$$M=begin{pmatrix}
2&2&2\
2&10&2\
2&2&2
end{pmatrix}$$
Commented
m => a => // m[] = input matrix, a[] = list of positions
a.map(([Y, X]) => ( // for each pair (X, Y) in a[]:
g = n => // g = recursive function expecting n = 0
m[ //
m.map((r, y) => // for each row r[] at position y in m[]:
r.map((_, x) => // for each value at position x in r[]:
(x - X) ** 2 + // if the quadrance between (x, y)
(y - Y) ** 2 < 3 // and (X, Y) is less than 3:
&& r[n++, x]++ // increment n and increment r[x]
) // end
), // end
(m[Y][X] += ~n) // subtract n + 1 from m[Y][X]
< n // if the result is greater than or equal to n:
|| g``, // do a recursive call
Y //
][X]++ // increment m[Y][X]
)`` // initial call to g
) // end
edited 46 mins ago
answered 4 hours ago
ArnauldArnauld
76.5k693321
76.5k693321
1
$begingroup$
You can save a couple of bytes by replacing both occurrences of(0)
with 2 backticks.
$endgroup$
– Shaggy
3 hours ago
add a comment |
1
$begingroup$
You can save a couple of bytes by replacing both occurrences of(0)
with 2 backticks.
$endgroup$
– Shaggy
3 hours ago
1
1
$begingroup$
You can save a couple of bytes by replacing both occurrences of
(0)
with 2 backticks.$endgroup$
– Shaggy
3 hours ago
$begingroup$
You can save a couple of bytes by replacing both occurrences of
(0)
with 2 backticks.$endgroup$
– Shaggy
3 hours ago
add a comment |
$begingroup$
Clean, 181 167 bytes
import StdEnv;
foldlm(x,y)={{if(d>2)0b+e-if(d>0)0b*n\e<-:l&v<-[0..],let{b=max m.[y,x]n/n;$a b=2+sign a-(a+1)/size b;n= $x l* $y m;d=(v-x)^2+(u-y)^2}}\l<-:m&u<-[0..]}
Try it online!
In the form of a partially-applied function literal.
Expanded (first version):
f // functinon f on {{Int}} and [(Int,Int)]
= foldl m (x, y) // fold :: (a -> b -> a) a [b] -> a with first argument {{Int}} (Int,Int) -> {{Int}} giving {{Int}} [(Int,Int)] -> {{Int}}
= { // an array of
{ // arrays of
if(d > 2) 0 b // the amount we give to the neighbors
+ e // plus the current entry
- if(d > 0) 0 b // minus the amount taken from the target entry
* n // times the number of neighbors, if we're on the target
\ // for each
e <-: l // element of row l
& v <- [0..] // and x-index v
, let // local definitions:
b // the amount given to the neighbors
= max // we need at least 1 each, so take the largest of
m.[y, x] // the target entry
n // or the number of neighbors
/ n // divide it by the number of neighbors
n // the number of neighbors
= ( // sum of
1 // one
+ s x // if x is at the left edge = 0 else 1
+ s ( // if x is at the right edge = 0 else 1
size l
- x
- 1
)
) * ( // times the sum of
1 // one
+ s y // if y is at the top edge = 0 else 1
+ s ( // if y is at the bottom edge = 0 else 1
size m
- y
- 1
)
)
d // distance from the target point
= (v - x)^2
+ (u - y)^2
}
\ // for each
l <-: m // row l in matrix m
& u <- [0..] // and y-index u
}
$endgroup$
add a comment |
$begingroup$
Clean, 181 167 bytes
import StdEnv;
foldlm(x,y)={{if(d>2)0b+e-if(d>0)0b*n\e<-:l&v<-[0..],let{b=max m.[y,x]n/n;$a b=2+sign a-(a+1)/size b;n= $x l* $y m;d=(v-x)^2+(u-y)^2}}\l<-:m&u<-[0..]}
Try it online!
In the form of a partially-applied function literal.
Expanded (first version):
f // functinon f on {{Int}} and [(Int,Int)]
= foldl m (x, y) // fold :: (a -> b -> a) a [b] -> a with first argument {{Int}} (Int,Int) -> {{Int}} giving {{Int}} [(Int,Int)] -> {{Int}}
= { // an array of
{ // arrays of
if(d > 2) 0 b // the amount we give to the neighbors
+ e // plus the current entry
- if(d > 0) 0 b // minus the amount taken from the target entry
* n // times the number of neighbors, if we're on the target
\ // for each
e <-: l // element of row l
& v <- [0..] // and x-index v
, let // local definitions:
b // the amount given to the neighbors
= max // we need at least 1 each, so take the largest of
m.[y, x] // the target entry
n // or the number of neighbors
/ n // divide it by the number of neighbors
n // the number of neighbors
= ( // sum of
1 // one
+ s x // if x is at the left edge = 0 else 1
+ s ( // if x is at the right edge = 0 else 1
size l
- x
- 1
)
) * ( // times the sum of
1 // one
+ s y // if y is at the top edge = 0 else 1
+ s ( // if y is at the bottom edge = 0 else 1
size m
- y
- 1
)
)
d // distance from the target point
= (v - x)^2
+ (u - y)^2
}
\ // for each
l <-: m // row l in matrix m
& u <- [0..] // and y-index u
}
$endgroup$
add a comment |
$begingroup$
Clean, 181 167 bytes
import StdEnv;
foldlm(x,y)={{if(d>2)0b+e-if(d>0)0b*n\e<-:l&v<-[0..],let{b=max m.[y,x]n/n;$a b=2+sign a-(a+1)/size b;n= $x l* $y m;d=(v-x)^2+(u-y)^2}}\l<-:m&u<-[0..]}
Try it online!
In the form of a partially-applied function literal.
Expanded (first version):
f // functinon f on {{Int}} and [(Int,Int)]
= foldl m (x, y) // fold :: (a -> b -> a) a [b] -> a with first argument {{Int}} (Int,Int) -> {{Int}} giving {{Int}} [(Int,Int)] -> {{Int}}
= { // an array of
{ // arrays of
if(d > 2) 0 b // the amount we give to the neighbors
+ e // plus the current entry
- if(d > 0) 0 b // minus the amount taken from the target entry
* n // times the number of neighbors, if we're on the target
\ // for each
e <-: l // element of row l
& v <- [0..] // and x-index v
, let // local definitions:
b // the amount given to the neighbors
= max // we need at least 1 each, so take the largest of
m.[y, x] // the target entry
n // or the number of neighbors
/ n // divide it by the number of neighbors
n // the number of neighbors
= ( // sum of
1 // one
+ s x // if x is at the left edge = 0 else 1
+ s ( // if x is at the right edge = 0 else 1
size l
- x
- 1
)
) * ( // times the sum of
1 // one
+ s y // if y is at the top edge = 0 else 1
+ s ( // if y is at the bottom edge = 0 else 1
size m
- y
- 1
)
)
d // distance from the target point
= (v - x)^2
+ (u - y)^2
}
\ // for each
l <-: m // row l in matrix m
& u <- [0..] // and y-index u
}
$endgroup$
Clean, 181 167 bytes
import StdEnv;
foldlm(x,y)={{if(d>2)0b+e-if(d>0)0b*n\e<-:l&v<-[0..],let{b=max m.[y,x]n/n;$a b=2+sign a-(a+1)/size b;n= $x l* $y m;d=(v-x)^2+(u-y)^2}}\l<-:m&u<-[0..]}
Try it online!
In the form of a partially-applied function literal.
Expanded (first version):
f // functinon f on {{Int}} and [(Int,Int)]
= foldl m (x, y) // fold :: (a -> b -> a) a [b] -> a with first argument {{Int}} (Int,Int) -> {{Int}} giving {{Int}} [(Int,Int)] -> {{Int}}
= { // an array of
{ // arrays of
if(d > 2) 0 b // the amount we give to the neighbors
+ e // plus the current entry
- if(d > 0) 0 b // minus the amount taken from the target entry
* n // times the number of neighbors, if we're on the target
\ // for each
e <-: l // element of row l
& v <- [0..] // and x-index v
, let // local definitions:
b // the amount given to the neighbors
= max // we need at least 1 each, so take the largest of
m.[y, x] // the target entry
n // or the number of neighbors
/ n // divide it by the number of neighbors
n // the number of neighbors
= ( // sum of
1 // one
+ s x // if x is at the left edge = 0 else 1
+ s ( // if x is at the right edge = 0 else 1
size l
- x
- 1
)
) * ( // times the sum of
1 // one
+ s y // if y is at the top edge = 0 else 1
+ s ( // if y is at the bottom edge = 0 else 1
size m
- y
- 1
)
)
d // distance from the target point
= (v - x)^2
+ (u - y)^2
}
\ // for each
l <-: m // row l in matrix m
& u <- [0..] // and y-index u
}
edited 12 hours ago
answered 13 hours ago
ΟurousΟurous
7,17111035
7,17111035
add a comment |
add a comment |
$begingroup$
Rust - 295 bytes
fn explode(p:(i8,i8),v:&mut Vec<Vec<i8>>){let x=v[p.0 as usize][p.1 as usize];let q=|x,y|x*x+y*y;loop{let mut t=0;for i in 0..v.len(){for j in 0..v[i].len(){if q(i as i8-p.0,j as i8-p.1)<3{v[i][j]+=1;v[p.0 as usize][p.1 as usize]-=1;t+=1;}}}if v[p.0 as usize][p.1 as usize]<=(x/t+x%t){break;}}}
This is pretty long due to Rust requiring unsigned integer indexing of vectors, but requiring signed integers to do subtraction resulting in negatives. However I believe my algorithm is the "shortest algorithm" so far. There is actually no need to deal with detecting edges, bottom, etc.
Notice three things: One, the sum of all cells is always constant. Two, this is a division / remainder situation, so we can apply Bresenham-algorithm style thinking. Three, the question always adds the same number to all cells within a certain distance of the special position cell, before dealing with the "extra" stuff in the special position.
Algorithm:
Store original value of cell at position P into M.
Begin Loop:
Iterate over each cell I in the matrix. If the position of cell I is within 3 Quadrance (squared distance) of the position P, then subtract 1 from cell P and add 1 to the cell I. Count how many times this is done in one iteration through the matrix.
If the value leftover in the cell at position P is less than or equal to M / Count + M modulo Count, then break the loop. Otherwise perform the loop again.
The resulting matrix will be the exploded version. Count is basically a way to count neighbors without dealing with edges. Looping is a way to break down the division/addition stuff into a repeated single addition/subtraction of one. The modulo check ensures we will have appropriate remainder left at position P to deal with 'explosions' that are not evenly divisible amongst neighbors. The do/while loop structure allows P<0 to work properly.
Ungolfed version on the Rust Playground
$endgroup$
$begingroup$
Such a long function name isn't necessary, any 1-byter such asf
would do. But you could probably save even more bytes, by using an anonymous function:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
add a comment |
$begingroup$
Rust - 295 bytes
fn explode(p:(i8,i8),v:&mut Vec<Vec<i8>>){let x=v[p.0 as usize][p.1 as usize];let q=|x,y|x*x+y*y;loop{let mut t=0;for i in 0..v.len(){for j in 0..v[i].len(){if q(i as i8-p.0,j as i8-p.1)<3{v[i][j]+=1;v[p.0 as usize][p.1 as usize]-=1;t+=1;}}}if v[p.0 as usize][p.1 as usize]<=(x/t+x%t){break;}}}
This is pretty long due to Rust requiring unsigned integer indexing of vectors, but requiring signed integers to do subtraction resulting in negatives. However I believe my algorithm is the "shortest algorithm" so far. There is actually no need to deal with detecting edges, bottom, etc.
Notice three things: One, the sum of all cells is always constant. Two, this is a division / remainder situation, so we can apply Bresenham-algorithm style thinking. Three, the question always adds the same number to all cells within a certain distance of the special position cell, before dealing with the "extra" stuff in the special position.
Algorithm:
Store original value of cell at position P into M.
Begin Loop:
Iterate over each cell I in the matrix. If the position of cell I is within 3 Quadrance (squared distance) of the position P, then subtract 1 from cell P and add 1 to the cell I. Count how many times this is done in one iteration through the matrix.
If the value leftover in the cell at position P is less than or equal to M / Count + M modulo Count, then break the loop. Otherwise perform the loop again.
The resulting matrix will be the exploded version. Count is basically a way to count neighbors without dealing with edges. Looping is a way to break down the division/addition stuff into a repeated single addition/subtraction of one. The modulo check ensures we will have appropriate remainder left at position P to deal with 'explosions' that are not evenly divisible amongst neighbors. The do/while loop structure allows P<0 to work properly.
Ungolfed version on the Rust Playground
$endgroup$
$begingroup$
Such a long function name isn't necessary, any 1-byter such asf
would do. But you could probably save even more bytes, by using an anonymous function:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
add a comment |
$begingroup$
Rust - 295 bytes
fn explode(p:(i8,i8),v:&mut Vec<Vec<i8>>){let x=v[p.0 as usize][p.1 as usize];let q=|x,y|x*x+y*y;loop{let mut t=0;for i in 0..v.len(){for j in 0..v[i].len(){if q(i as i8-p.0,j as i8-p.1)<3{v[i][j]+=1;v[p.0 as usize][p.1 as usize]-=1;t+=1;}}}if v[p.0 as usize][p.1 as usize]<=(x/t+x%t){break;}}}
This is pretty long due to Rust requiring unsigned integer indexing of vectors, but requiring signed integers to do subtraction resulting in negatives. However I believe my algorithm is the "shortest algorithm" so far. There is actually no need to deal with detecting edges, bottom, etc.
Notice three things: One, the sum of all cells is always constant. Two, this is a division / remainder situation, so we can apply Bresenham-algorithm style thinking. Three, the question always adds the same number to all cells within a certain distance of the special position cell, before dealing with the "extra" stuff in the special position.
Algorithm:
Store original value of cell at position P into M.
Begin Loop:
Iterate over each cell I in the matrix. If the position of cell I is within 3 Quadrance (squared distance) of the position P, then subtract 1 from cell P and add 1 to the cell I. Count how many times this is done in one iteration through the matrix.
If the value leftover in the cell at position P is less than or equal to M / Count + M modulo Count, then break the loop. Otherwise perform the loop again.
The resulting matrix will be the exploded version. Count is basically a way to count neighbors without dealing with edges. Looping is a way to break down the division/addition stuff into a repeated single addition/subtraction of one. The modulo check ensures we will have appropriate remainder left at position P to deal with 'explosions' that are not evenly divisible amongst neighbors. The do/while loop structure allows P<0 to work properly.
Ungolfed version on the Rust Playground
$endgroup$
Rust - 295 bytes
fn explode(p:(i8,i8),v:&mut Vec<Vec<i8>>){let x=v[p.0 as usize][p.1 as usize];let q=|x,y|x*x+y*y;loop{let mut t=0;for i in 0..v.len(){for j in 0..v[i].len(){if q(i as i8-p.0,j as i8-p.1)<3{v[i][j]+=1;v[p.0 as usize][p.1 as usize]-=1;t+=1;}}}if v[p.0 as usize][p.1 as usize]<=(x/t+x%t){break;}}}
This is pretty long due to Rust requiring unsigned integer indexing of vectors, but requiring signed integers to do subtraction resulting in negatives. However I believe my algorithm is the "shortest algorithm" so far. There is actually no need to deal with detecting edges, bottom, etc.
Notice three things: One, the sum of all cells is always constant. Two, this is a division / remainder situation, so we can apply Bresenham-algorithm style thinking. Three, the question always adds the same number to all cells within a certain distance of the special position cell, before dealing with the "extra" stuff in the special position.
Algorithm:
Store original value of cell at position P into M.
Begin Loop:
Iterate over each cell I in the matrix. If the position of cell I is within 3 Quadrance (squared distance) of the position P, then subtract 1 from cell P and add 1 to the cell I. Count how many times this is done in one iteration through the matrix.
If the value leftover in the cell at position P is less than or equal to M / Count + M modulo Count, then break the loop. Otherwise perform the loop again.
The resulting matrix will be the exploded version. Count is basically a way to count neighbors without dealing with edges. Looping is a way to break down the division/addition stuff into a repeated single addition/subtraction of one. The modulo check ensures we will have appropriate remainder left at position P to deal with 'explosions' that are not evenly divisible amongst neighbors. The do/while loop structure allows P<0 to work properly.
Ungolfed version on the Rust Playground
edited 8 hours ago
answered 8 hours ago
don brightdon bright
506410
506410
$begingroup$
Such a long function name isn't necessary, any 1-byter such asf
would do. But you could probably save even more bytes, by using an anonymous function:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
add a comment |
$begingroup$
Such a long function name isn't necessary, any 1-byter such asf
would do. But you could probably save even more bytes, by using an anonymous function:|p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
$begingroup$
Such a long function name isn't necessary, any 1-byter such as
f
would do. But you could probably save even more bytes, by using an anonymous function: |p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
$begingroup$
Such a long function name isn't necessary, any 1-byter such as
f
would do. But you could probably save even more bytes, by using an anonymous function: |p:(i8,i8),v:&mut Vec<Vec<i8>>|{...}
$endgroup$
– Kirill L.
21 secs ago
add a comment |
$begingroup$
R, 163 162 161 159 bytes
function(m,l){for(e in l){i=e[1];j=e[2];x=-1:1+i;y=-1:1+j;s=m[x<-x[x<=dim(m)],y<-y[y<=ncol(m)]];z=sum(1|s);d=max(1,m[i,j]%/%z);m[x,y]=s+d;m[i,j]=m[i,j]-d*z};m}
Try it online!
Explanation
function(m,l) { # Take input as matrix m and 1-indexed list of explosion points l
for(e in l) { # Loop over the list of explosion points
i=e[1]; j=e[2] # Assign current coordinates to (i,j) for brevity
x=-1:1+i # Assign the ranges of neighboring cells: (i-1) to (i+1),
y=-1:1+j # and (j-1) to (j+1)
s= # Take the submatrix s=m[x,y]
m[x<-x[x<=dim(m)] # But first trim x and y from above to prevent out of bounds errors,
,y<-y[y<=ncol(m)]] # trimming from below isn't necessary, as R tolerates index 0
z=sum(1|s) # Count the neighbors
d=max(1,m[i,j]%/%z) # Estimate, how much we'll distribute to each neighbor
m[x,y]=s+d # Add the distributed amount to each cell of the submatrix
m[i,j]=m[i,j]-d*z # Subtract the total amount from the exploded cell
}
m # Return the modified matrix
}
$endgroup$
add a comment |
$begingroup$
R, 163 162 161 159 bytes
function(m,l){for(e in l){i=e[1];j=e[2];x=-1:1+i;y=-1:1+j;s=m[x<-x[x<=dim(m)],y<-y[y<=ncol(m)]];z=sum(1|s);d=max(1,m[i,j]%/%z);m[x,y]=s+d;m[i,j]=m[i,j]-d*z};m}
Try it online!
Explanation
function(m,l) { # Take input as matrix m and 1-indexed list of explosion points l
for(e in l) { # Loop over the list of explosion points
i=e[1]; j=e[2] # Assign current coordinates to (i,j) for brevity
x=-1:1+i # Assign the ranges of neighboring cells: (i-1) to (i+1),
y=-1:1+j # and (j-1) to (j+1)
s= # Take the submatrix s=m[x,y]
m[x<-x[x<=dim(m)] # But first trim x and y from above to prevent out of bounds errors,
,y<-y[y<=ncol(m)]] # trimming from below isn't necessary, as R tolerates index 0
z=sum(1|s) # Count the neighbors
d=max(1,m[i,j]%/%z) # Estimate, how much we'll distribute to each neighbor
m[x,y]=s+d # Add the distributed amount to each cell of the submatrix
m[i,j]=m[i,j]-d*z # Subtract the total amount from the exploded cell
}
m # Return the modified matrix
}
$endgroup$
add a comment |
$begingroup$
R, 163 162 161 159 bytes
function(m,l){for(e in l){i=e[1];j=e[2];x=-1:1+i;y=-1:1+j;s=m[x<-x[x<=dim(m)],y<-y[y<=ncol(m)]];z=sum(1|s);d=max(1,m[i,j]%/%z);m[x,y]=s+d;m[i,j]=m[i,j]-d*z};m}
Try it online!
Explanation
function(m,l) { # Take input as matrix m and 1-indexed list of explosion points l
for(e in l) { # Loop over the list of explosion points
i=e[1]; j=e[2] # Assign current coordinates to (i,j) for brevity
x=-1:1+i # Assign the ranges of neighboring cells: (i-1) to (i+1),
y=-1:1+j # and (j-1) to (j+1)
s= # Take the submatrix s=m[x,y]
m[x<-x[x<=dim(m)] # But first trim x and y from above to prevent out of bounds errors,
,y<-y[y<=ncol(m)]] # trimming from below isn't necessary, as R tolerates index 0
z=sum(1|s) # Count the neighbors
d=max(1,m[i,j]%/%z) # Estimate, how much we'll distribute to each neighbor
m[x,y]=s+d # Add the distributed amount to each cell of the submatrix
m[i,j]=m[i,j]-d*z # Subtract the total amount from the exploded cell
}
m # Return the modified matrix
}
$endgroup$
R, 163 162 161 159 bytes
function(m,l){for(e in l){i=e[1];j=e[2];x=-1:1+i;y=-1:1+j;s=m[x<-x[x<=dim(m)],y<-y[y<=ncol(m)]];z=sum(1|s);d=max(1,m[i,j]%/%z);m[x,y]=s+d;m[i,j]=m[i,j]-d*z};m}
Try it online!
Explanation
function(m,l) { # Take input as matrix m and 1-indexed list of explosion points l
for(e in l) { # Loop over the list of explosion points
i=e[1]; j=e[2] # Assign current coordinates to (i,j) for brevity
x=-1:1+i # Assign the ranges of neighboring cells: (i-1) to (i+1),
y=-1:1+j # and (j-1) to (j+1)
s= # Take the submatrix s=m[x,y]
m[x<-x[x<=dim(m)] # But first trim x and y from above to prevent out of bounds errors,
,y<-y[y<=ncol(m)]] # trimming from below isn't necessary, as R tolerates index 0
z=sum(1|s) # Count the neighbors
d=max(1,m[i,j]%/%z) # Estimate, how much we'll distribute to each neighbor
m[x,y]=s+d # Add the distributed amount to each cell of the submatrix
m[i,j]=m[i,j]-d*z # Subtract the total amount from the exploded cell
}
m # Return the modified matrix
}
edited 20 mins ago
answered 3 hours ago
Kirill L.Kirill L.
4,4451523
4,4451523
add a comment |
add a comment |
$begingroup$
Common Lisp, 498 bytes
(defmacro s(l c x)`(incf(aref m,l,c),x))
(defmacro w(a &rest f)`(if(,a(or(= l 0)(= l(d 0)))(or(= c 0)(= c(d 1)))),@f))
(defmacro d(n)`(1-(array-dimension m,n)))
(defmacro p(i l m &rest f)`(loop for,i from(1-,l)to(1+,l)when(and(>=,i 0)(<=,i,m))do,@f))
(defmacro g()`(or(p i l(d 0)(p j c(d 1)(s i j 1)))(s l c(- v))))
(defun f(m l c)(let((v(w and 4(w or 6 9))))(if (<(/(s l c 0)v)1)(g)(loop for i to(1-(/(s l c 0)v))do(g)))))
(defun c(m n)(dotimes(i(length n))(f m(nth 0(nth i n))(nth 1(nth i n))))m)
Try it online!
Use this function as (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
Better readable version:
(defmacro s (l c x)
`(incf (aref m ,l ,c) ,x))
(defmacro w (a &rest f)
`(if (,a (or (= l 0)
(= l (d 0)))
(or (= c 0)
(= c (d 1))))
,@f))
(defmacro d (n)
`(1- (array-dimension m ,n)))
(defmacro p (i l m &rest f)
`(loop for ,i from (1- ,l) to (1+ ,l)
when (and (>= ,i 0) (<= ,i ,m))
do ,@f))
(defmacro g ()
`(or(p i l (d 0)
(p j c (d 1)
(s i j 1)))
(s l c (- v))))
(defun f (m l c)
(let ((v (w and 4 (w or 6 9))))
(if (< (/ (s l c 0) v) 1)
(g)
(loop for i to (1- (/ (s l c 0) v))
do (g)))))
(defun c (m n)
(dotimes (i (length n))
(f m (nth 0 (nth i n))
(nth 1 (nth i n))))
m)
Output example:
(print (c #2A((3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3)) '((5 0)(4 1)(0 2))))
;; #2A((3 4 0) (3 4 4) (3 3 3) (4 4 4) (5 -4 4) (1 5 4))
(print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
; #2A((1 0 1) (5 6 5) (3 3 3)) => #2A((1 0 1) (5 6 5) (3 3 3))
(print (c #2A((9 8 7) (8 9 7) (8 7 9)) '((0 0)(1 1)(2 2))))
;; #2A((4 11 8) (11 5 10) (9 10 4)) => #2A((4 11 8) (11 5 10) (9 10 4))
(print (c #2A((0 0) (0 0)) '((0 0)(0 0)(0 0))))
;; #2A((-9 3) (3 3)) => #2A((-9 3) (3 3))
(print (c #2A((10 20 30)(30 20 10)(40 50 60)) '((0 2)(2 0)(1 1)(1 0))))
;; #2A((21 38 13) (9 12 21) (21 71 64)) => #2A((21 38 13) (9 12 21) (21 71 64))
New contributor
$endgroup$
add a comment |
$begingroup$
Common Lisp, 498 bytes
(defmacro s(l c x)`(incf(aref m,l,c),x))
(defmacro w(a &rest f)`(if(,a(or(= l 0)(= l(d 0)))(or(= c 0)(= c(d 1)))),@f))
(defmacro d(n)`(1-(array-dimension m,n)))
(defmacro p(i l m &rest f)`(loop for,i from(1-,l)to(1+,l)when(and(>=,i 0)(<=,i,m))do,@f))
(defmacro g()`(or(p i l(d 0)(p j c(d 1)(s i j 1)))(s l c(- v))))
(defun f(m l c)(let((v(w and 4(w or 6 9))))(if (<(/(s l c 0)v)1)(g)(loop for i to(1-(/(s l c 0)v))do(g)))))
(defun c(m n)(dotimes(i(length n))(f m(nth 0(nth i n))(nth 1(nth i n))))m)
Try it online!
Use this function as (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
Better readable version:
(defmacro s (l c x)
`(incf (aref m ,l ,c) ,x))
(defmacro w (a &rest f)
`(if (,a (or (= l 0)
(= l (d 0)))
(or (= c 0)
(= c (d 1))))
,@f))
(defmacro d (n)
`(1- (array-dimension m ,n)))
(defmacro p (i l m &rest f)
`(loop for ,i from (1- ,l) to (1+ ,l)
when (and (>= ,i 0) (<= ,i ,m))
do ,@f))
(defmacro g ()
`(or(p i l (d 0)
(p j c (d 1)
(s i j 1)))
(s l c (- v))))
(defun f (m l c)
(let ((v (w and 4 (w or 6 9))))
(if (< (/ (s l c 0) v) 1)
(g)
(loop for i to (1- (/ (s l c 0) v))
do (g)))))
(defun c (m n)
(dotimes (i (length n))
(f m (nth 0 (nth i n))
(nth 1 (nth i n))))
m)
Output example:
(print (c #2A((3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3)) '((5 0)(4 1)(0 2))))
;; #2A((3 4 0) (3 4 4) (3 3 3) (4 4 4) (5 -4 4) (1 5 4))
(print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
; #2A((1 0 1) (5 6 5) (3 3 3)) => #2A((1 0 1) (5 6 5) (3 3 3))
(print (c #2A((9 8 7) (8 9 7) (8 7 9)) '((0 0)(1 1)(2 2))))
;; #2A((4 11 8) (11 5 10) (9 10 4)) => #2A((4 11 8) (11 5 10) (9 10 4))
(print (c #2A((0 0) (0 0)) '((0 0)(0 0)(0 0))))
;; #2A((-9 3) (3 3)) => #2A((-9 3) (3 3))
(print (c #2A((10 20 30)(30 20 10)(40 50 60)) '((0 2)(2 0)(1 1)(1 0))))
;; #2A((21 38 13) (9 12 21) (21 71 64)) => #2A((21 38 13) (9 12 21) (21 71 64))
New contributor
$endgroup$
add a comment |
$begingroup$
Common Lisp, 498 bytes
(defmacro s(l c x)`(incf(aref m,l,c),x))
(defmacro w(a &rest f)`(if(,a(or(= l 0)(= l(d 0)))(or(= c 0)(= c(d 1)))),@f))
(defmacro d(n)`(1-(array-dimension m,n)))
(defmacro p(i l m &rest f)`(loop for,i from(1-,l)to(1+,l)when(and(>=,i 0)(<=,i,m))do,@f))
(defmacro g()`(or(p i l(d 0)(p j c(d 1)(s i j 1)))(s l c(- v))))
(defun f(m l c)(let((v(w and 4(w or 6 9))))(if (<(/(s l c 0)v)1)(g)(loop for i to(1-(/(s l c 0)v))do(g)))))
(defun c(m n)(dotimes(i(length n))(f m(nth 0(nth i n))(nth 1(nth i n))))m)
Try it online!
Use this function as (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
Better readable version:
(defmacro s (l c x)
`(incf (aref m ,l ,c) ,x))
(defmacro w (a &rest f)
`(if (,a (or (= l 0)
(= l (d 0)))
(or (= c 0)
(= c (d 1))))
,@f))
(defmacro d (n)
`(1- (array-dimension m ,n)))
(defmacro p (i l m &rest f)
`(loop for ,i from (1- ,l) to (1+ ,l)
when (and (>= ,i 0) (<= ,i ,m))
do ,@f))
(defmacro g ()
`(or(p i l (d 0)
(p j c (d 1)
(s i j 1)))
(s l c (- v))))
(defun f (m l c)
(let ((v (w and 4 (w or 6 9))))
(if (< (/ (s l c 0) v) 1)
(g)
(loop for i to (1- (/ (s l c 0) v))
do (g)))))
(defun c (m n)
(dotimes (i (length n))
(f m (nth 0 (nth i n))
(nth 1 (nth i n))))
m)
Output example:
(print (c #2A((3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3)) '((5 0)(4 1)(0 2))))
;; #2A((3 4 0) (3 4 4) (3 3 3) (4 4 4) (5 -4 4) (1 5 4))
(print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
; #2A((1 0 1) (5 6 5) (3 3 3)) => #2A((1 0 1) (5 6 5) (3 3 3))
(print (c #2A((9 8 7) (8 9 7) (8 7 9)) '((0 0)(1 1)(2 2))))
;; #2A((4 11 8) (11 5 10) (9 10 4)) => #2A((4 11 8) (11 5 10) (9 10 4))
(print (c #2A((0 0) (0 0)) '((0 0)(0 0)(0 0))))
;; #2A((-9 3) (3 3)) => #2A((-9 3) (3 3))
(print (c #2A((10 20 30)(30 20 10)(40 50 60)) '((0 2)(2 0)(1 1)(1 0))))
;; #2A((21 38 13) (9 12 21) (21 71 64)) => #2A((21 38 13) (9 12 21) (21 71 64))
New contributor
$endgroup$
Common Lisp, 498 bytes
(defmacro s(l c x)`(incf(aref m,l,c),x))
(defmacro w(a &rest f)`(if(,a(or(= l 0)(= l(d 0)))(or(= c 0)(= c(d 1)))),@f))
(defmacro d(n)`(1-(array-dimension m,n)))
(defmacro p(i l m &rest f)`(loop for,i from(1-,l)to(1+,l)when(and(>=,i 0)(<=,i,m))do,@f))
(defmacro g()`(or(p i l(d 0)(p j c(d 1)(s i j 1)))(s l c(- v))))
(defun f(m l c)(let((v(w and 4(w or 6 9))))(if (<(/(s l c 0)v)1)(g)(loop for i to(1-(/(s l c 0)v))do(g)))))
(defun c(m n)(dotimes(i(length n))(f m(nth 0(nth i n))(nth 1(nth i n))))m)
Try it online!
Use this function as (print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
Better readable version:
(defmacro s (l c x)
`(incf (aref m ,l ,c) ,x))
(defmacro w (a &rest f)
`(if (,a (or (= l 0)
(= l (d 0)))
(or (= c 0)
(= c (d 1))))
,@f))
(defmacro d (n)
`(1- (array-dimension m ,n)))
(defmacro p (i l m &rest f)
`(loop for ,i from (1- ,l) to (1+ ,l)
when (and (>= ,i 0) (<= ,i ,m))
do ,@f))
(defmacro g ()
`(or(p i l (d 0)
(p j c (d 1)
(s i j 1)))
(s l c (- v))))
(defun f (m l c)
(let ((v (w and 4 (w or 6 9))))
(if (< (/ (s l c 0) v) 1)
(g)
(loop for i to (1- (/ (s l c 0) v))
do (g)))))
(defun c (m n)
(dotimes (i (length n))
(f m (nth 0 (nth i n))
(nth 1 (nth i n))))
m)
Output example:
(print (c #2A((3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3) (3 3 3)) '((5 0)(4 1)(0 2))))
;; #2A((3 4 0) (3 4 4) (3 3 3) (4 4 4) (5 -4 4) (1 5 4))
(print (c #2A((3 3 3) (3 3 3) (3 3 3)) '((0 0)(0 1)(0 2))))
; #2A((1 0 1) (5 6 5) (3 3 3)) => #2A((1 0 1) (5 6 5) (3 3 3))
(print (c #2A((9 8 7) (8 9 7) (8 7 9)) '((0 0)(1 1)(2 2))))
;; #2A((4 11 8) (11 5 10) (9 10 4)) => #2A((4 11 8) (11 5 10) (9 10 4))
(print (c #2A((0 0) (0 0)) '((0 0)(0 0)(0 0))))
;; #2A((-9 3) (3 3)) => #2A((-9 3) (3 3))
(print (c #2A((10 20 30)(30 20 10)(40 50 60)) '((0 2)(2 0)(1 1)(1 0))))
;; #2A((21 38 13) (9 12 21) (21 71 64)) => #2A((21 38 13) (9 12 21) (21 71 64))
New contributor
New contributor
answered 5 hours ago
adladl
1712
1712
New contributor
New contributor
add a comment |
add a comment |
$begingroup$
Java 10, 194 193 bytes
M->C->{for(var q:C){int f=1,n=0,X=q[0],Y=q[1],x,y,c=1,t;for(;f>0;f=(M[X][Y]+=~n)<n?0:c++)for(n=0,x=M.length;x-->0;)for(y=M[x].length;y-->0;)if((t=x-X)*t+(t=y-Y)*t<3)M[x][y]+=++n/n;M[X][Y]+=c;}}
Iterative port of @Arnauld's JavaScript answer.
Modifies the input-matrix instead of returning a new one to save bytes.
Try it online.
Explanation:
M->C->{ // Method with two integer-matrix parameters and no return-type
for(var q:C){ // Loop over the coordinates:
int f=1, // Flag integer, starting at 1 for every coordinate
n=0, // Count integer, starting at 0 for every coordinate
X=q[0],Y=q[1], // The current X,Y coordinate
x,y, // Temp x,y coordinates
c=1, // Counter, starting at 1
t; // Temp integer
for(;f>0 // Loop as long as the flag is not 0:
; // After every iteration:
f=(M[X][Y]+=~n) // Decrease the value at X,Y by n+1
<n? // If it's now smaller than the count `n`
0 // Change the flag to 0
: // Else:
c++) // Change the flag to counter `c`, and increase `c` by 1
for(n=0, // Reset the count `n` to 0
x=M.length;x-->0;)// Loop `x` over the rows:
for(y=M[x].length;y-->0;)
// Inner loop `y` over the columns:
if((t=x-X)*t // If the difference between `x` and `X` squared
+(t=y-Y)*t // and the difference between `y` and `Y` squared together
<3){ // Is smaller than 3:
M[x][y]+=++n/n; // Increase count `n` and the value at x,y both by 1
M[X][Y]+=c;}} // Increase the value at X,Y with counter `c`
$endgroup$
1
$begingroup$
Is thetry/catch
really required?
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
1
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), butm[y][x]
with $y$ out of bounds would crash as well.
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand whyundefined[x]
would fail. Anyway, your(x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.
$endgroup$
– Kevin Cruijssen
1 hour ago
add a comment |
$begingroup$
Java 10, 194 193 bytes
M->C->{for(var q:C){int f=1,n=0,X=q[0],Y=q[1],x,y,c=1,t;for(;f>0;f=(M[X][Y]+=~n)<n?0:c++)for(n=0,x=M.length;x-->0;)for(y=M[x].length;y-->0;)if((t=x-X)*t+(t=y-Y)*t<3)M[x][y]+=++n/n;M[X][Y]+=c;}}
Iterative port of @Arnauld's JavaScript answer.
Modifies the input-matrix instead of returning a new one to save bytes.
Try it online.
Explanation:
M->C->{ // Method with two integer-matrix parameters and no return-type
for(var q:C){ // Loop over the coordinates:
int f=1, // Flag integer, starting at 1 for every coordinate
n=0, // Count integer, starting at 0 for every coordinate
X=q[0],Y=q[1], // The current X,Y coordinate
x,y, // Temp x,y coordinates
c=1, // Counter, starting at 1
t; // Temp integer
for(;f>0 // Loop as long as the flag is not 0:
; // After every iteration:
f=(M[X][Y]+=~n) // Decrease the value at X,Y by n+1
<n? // If it's now smaller than the count `n`
0 // Change the flag to 0
: // Else:
c++) // Change the flag to counter `c`, and increase `c` by 1
for(n=0, // Reset the count `n` to 0
x=M.length;x-->0;)// Loop `x` over the rows:
for(y=M[x].length;y-->0;)
// Inner loop `y` over the columns:
if((t=x-X)*t // If the difference between `x` and `X` squared
+(t=y-Y)*t // and the difference between `y` and `Y` squared together
<3){ // Is smaller than 3:
M[x][y]+=++n/n; // Increase count `n` and the value at x,y both by 1
M[X][Y]+=c;}} // Increase the value at X,Y with counter `c`
$endgroup$
1
$begingroup$
Is thetry/catch
really required?
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
1
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), butm[y][x]
with $y$ out of bounds would crash as well.
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand whyundefined[x]
would fail. Anyway, your(x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.
$endgroup$
– Kevin Cruijssen
1 hour ago
add a comment |
$begingroup$
Java 10, 194 193 bytes
M->C->{for(var q:C){int f=1,n=0,X=q[0],Y=q[1],x,y,c=1,t;for(;f>0;f=(M[X][Y]+=~n)<n?0:c++)for(n=0,x=M.length;x-->0;)for(y=M[x].length;y-->0;)if((t=x-X)*t+(t=y-Y)*t<3)M[x][y]+=++n/n;M[X][Y]+=c;}}
Iterative port of @Arnauld's JavaScript answer.
Modifies the input-matrix instead of returning a new one to save bytes.
Try it online.
Explanation:
M->C->{ // Method with two integer-matrix parameters and no return-type
for(var q:C){ // Loop over the coordinates:
int f=1, // Flag integer, starting at 1 for every coordinate
n=0, // Count integer, starting at 0 for every coordinate
X=q[0],Y=q[1], // The current X,Y coordinate
x,y, // Temp x,y coordinates
c=1, // Counter, starting at 1
t; // Temp integer
for(;f>0 // Loop as long as the flag is not 0:
; // After every iteration:
f=(M[X][Y]+=~n) // Decrease the value at X,Y by n+1
<n? // If it's now smaller than the count `n`
0 // Change the flag to 0
: // Else:
c++) // Change the flag to counter `c`, and increase `c` by 1
for(n=0, // Reset the count `n` to 0
x=M.length;x-->0;)// Loop `x` over the rows:
for(y=M[x].length;y-->0;)
// Inner loop `y` over the columns:
if((t=x-X)*t // If the difference between `x` and `X` squared
+(t=y-Y)*t // and the difference between `y` and `Y` squared together
<3){ // Is smaller than 3:
M[x][y]+=++n/n; // Increase count `n` and the value at x,y both by 1
M[X][Y]+=c;}} // Increase the value at X,Y with counter `c`
$endgroup$
Java 10, 194 193 bytes
M->C->{for(var q:C){int f=1,n=0,X=q[0],Y=q[1],x,y,c=1,t;for(;f>0;f=(M[X][Y]+=~n)<n?0:c++)for(n=0,x=M.length;x-->0;)for(y=M[x].length;y-->0;)if((t=x-X)*t+(t=y-Y)*t<3)M[x][y]+=++n/n;M[X][Y]+=c;}}
Iterative port of @Arnauld's JavaScript answer.
Modifies the input-matrix instead of returning a new one to save bytes.
Try it online.
Explanation:
M->C->{ // Method with two integer-matrix parameters and no return-type
for(var q:C){ // Loop over the coordinates:
int f=1, // Flag integer, starting at 1 for every coordinate
n=0, // Count integer, starting at 0 for every coordinate
X=q[0],Y=q[1], // The current X,Y coordinate
x,y, // Temp x,y coordinates
c=1, // Counter, starting at 1
t; // Temp integer
for(;f>0 // Loop as long as the flag is not 0:
; // After every iteration:
f=(M[X][Y]+=~n) // Decrease the value at X,Y by n+1
<n? // If it's now smaller than the count `n`
0 // Change the flag to 0
: // Else:
c++) // Change the flag to counter `c`, and increase `c` by 1
for(n=0, // Reset the count `n` to 0
x=M.length;x-->0;)// Loop `x` over the rows:
for(y=M[x].length;y-->0;)
// Inner loop `y` over the columns:
if((t=x-X)*t // If the difference between `x` and `X` squared
+(t=y-Y)*t // and the difference between `y` and `Y` squared together
<3){ // Is smaller than 3:
M[x][y]+=++n/n; // Increase count `n` and the value at x,y both by 1
M[X][Y]+=c;}} // Increase the value at X,Y with counter `c`
edited 31 mins ago
answered 1 hour ago
Kevin CruijssenKevin Cruijssen
38.4k557199
38.4k557199
1
$begingroup$
Is thetry/catch
really required?
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
1
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), butm[y][x]
with $y$ out of bounds would crash as well.
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand whyundefined[x]
would fail. Anyway, your(x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.
$endgroup$
– Kevin Cruijssen
1 hour ago
add a comment |
1
$begingroup$
Is thetry/catch
really required?
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
1
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), butm[y][x]
with $y$ out of bounds would crash as well.
$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand whyundefined[x]
would fail. Anyway, your(x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.
$endgroup$
– Kevin Cruijssen
1 hour ago
1
1
$begingroup$
Is the
try/catch
really required?$endgroup$
– Arnauld
1 hour ago
$begingroup$
Is the
try/catch
really required?$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
$begingroup$
@Arnauld Oops.. It's indeed not necessary. Removed. I falsely assumed JavaScript automatically handles/ignores out of bounds, and I had to do it manually. Didn't realize your check covers that as well. ;)
$endgroup$
– Kevin Cruijssen
1 hour ago
1
1
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), but m[y][x]
with $y$ out of bounds would crash as well.$endgroup$
– Arnauld
1 hour ago
$begingroup$
m[y]
with $y$ out of bounds is OK in JS (yielding undefined), but m[y][x]
with $y$ out of bounds would crash as well.$endgroup$
– Arnauld
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand why
undefined[x]
would fail. Anyway, your (x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.$endgroup$
– Kevin Cruijssen
1 hour ago
$begingroup$
@Arnauld Ah ok. I indeed remembered out of bounds usually isn't an issue in JS, but I can understand why
undefined[x]
would fail. Anyway, your (x-X)**2+(y-Y)**2<3
check is pretty smart. Need to remember that when I ever want to check values in a matrix in a 3x3 block (and within bounds) around it. I think I actually have a few answers like that, where I now use a try-catch, and in one case try-finally.. Will look at those when I have some time.$endgroup$
– Kevin Cruijssen
1 hour ago
add a comment |
If this is an answer to a challenge…
…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.
…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.
More generally…
…Please make sure to answer the question and provide sufficient detail.
…Avoid asking for help, clarification or responding to other answers (use comments instead).
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f180188%2fexploding-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
new to code golf; what format is the sample allowed to take these matrices in? Any format that exists in the language? String form exactly as written?
$endgroup$
– rtpax
18 hours ago
1
$begingroup$
I suggest adding a test case for non-square matricies.
$endgroup$
– Οurous
16 hours ago
$begingroup$
@Ourous uh oh, I had been writing my program assuming they were guaranteed to be square, back to the drawing board I guess
$endgroup$
– rtpax
16 hours ago
$begingroup$
Can we assume the matrix-size is at least 2 by 2? Or can a 1 by 1 matrix be input as well?
$endgroup$
– Kevin Cruijssen
3 hours ago