17
\$\begingroup\$

Generate a 7 by 7 grid, filled with random numbers. However, in cells with an odd row and column number (starting at 0), you must use the sum of the surrounding cells. Here's a small example with a 3 by 3 grid (sum-square bolded):

2 2 2
2 16 2
2 2 2

And here's an example 7 by 7 grid:

6 5 4 3 7 2 5
6 43 3 50 8 43 8
4 7 8 8 9 3 1
4 36 1 43 6 40 5
3 3 6 1 4 7 5
4 35 3 45 9 42 1
2 6 8 6 8 5 3

Rules

  • Numbers that are not sums must always be between 1 and 9 inclusive.

  • Grid must be randomly generated. For each non-sum, every digit must have an equal chance of appearing, regardless of which cell it is in.

  • Numbers must be aligned. This means that either the first or last digit of each number in a column must line up vertically. (You may assume that the middle numbers will always be two digits.)

  • Surrounding cells includes diagonals. Therefore, each sum square will have eight numbers surrounding it, which you must add.

  • Shortest code wins, since this is .

asked Aug 31, 2013 at 2:37
\$\endgroup\$
3
  • 3
    \$\begingroup\$ Does it have to be the first digit that lines up? i.e. can it be the last? \$\endgroup\$ Commented Aug 31, 2013 at 6:28
  • \$\begingroup\$ @Volatility I suppose right align would work. edited \$\endgroup\$ Commented Aug 31, 2013 at 13:14
  • \$\begingroup\$ What if a language doesn't have a random number generator? \$\endgroup\$ Commented Nov 2, 2017 at 11:24

20 Answers 20

15
\$\begingroup\$

APL, (削除) 53 49 43 42 40 39 (削除ここまで) 36

I managed to replicate J's ;. in APL, and used Gareth's approach, saving 13 chars.

×ばつ5⌷⍵:5⌷⍵⋄+/⍵} ×ばつ∘?∘9 ̈∘.∨⍨9⍴0 1

Sample run:

 ×ばつ5⌷⍵:5⌷⍵⋄+/⍵} ×ばつ∘?∘9 ̈∘.∨⍨9⍴0 1
9 9 6 1 7 5 6
7 55 5 39 9 54 9
9 8 2 1 8 1 9
2 43 8 41 6 42 5
7 3 4 4 8 3 2
2 29 1 26 2 35 8
6 4 2 3 2 3 7

Explanation:

  • ∘.∨⍨9⍴0 1 generates a bit mask.
  • ×ばつ∘?∘9 ̈ multiplies each bit by a random value from 1 to 9 inclusive, generating a masked grid of random numbers.
  • 3,⌿3,/ uses what can only be described as hackery to return all 3 by 3 overlapping boxes in the masked array. These are also flattened in the process.
  • ×ばつ5⌷⍵:5⌷⍵⋄+/⍵} ̈ iterates over the array, assigning each element to . For each iteration, it takes the fifth (middle, remembering that APL indexing is 1-based), and returns its sign. In this case this is equivalent to testing if the number is greater than 0. If this returns 1 (for true), then return that element. Otherwise, return the sum of the elements in the flattened 3 by 3 box. It uses the :⋄ ternary operator, which is the equivalent of ?: in many languages.
answered Aug 31, 2013 at 7:32
\$\endgroup\$
3
  • \$\begingroup\$ Uh-oh. Looks like I'm going to have to find more character savings. :-S \$\endgroup\$ Commented Sep 3, 2013 at 10:31
  • \$\begingroup\$ @Gareth well, look what we have here. I'm back in the lead :P \$\endgroup\$ Commented Sep 3, 2013 at 10:41
  • \$\begingroup\$ NOOOOOOOOOO!!!!!!! :-( \$\endgroup\$ Commented Sep 3, 2013 at 11:53
12
\$\begingroup\$

J, (削除) 63 (削除ここまで) (削除) 61 (削除ここまで) (削除) 59 (削除ここまで) (削除) 55 (削除ここまで) (削除) 52 (削除ここまで) (削除) 51 (削除ここまで) (削除) 49 (削除ここまで) (削除) 47 (削除ここまで) (削除) 39 (削除ここまで) 37 characters

3 3(4&{+4{*|+/)@,;._3(**1+?)+./~90ドル 9

With thanks to Volatility for his 10 character saving.

Explanation (each step will have different random numbers...):

Generate the mask for generating the random numbers (uses $:

 9 99ドル0ドル 9
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0
0 9 0 9 0 9 0 9 0

Now we have a hook. This is actually a happy accident from when I was whittling down an earlier version. It was meant to be transpose |: and OR +. with the original. It made sense since I was using ones and zeroes at the time, but now I have nines and zeroes. It just so happens that it works in the same way with the GCD meaning of +.. Lucky for me. :-)

 (+.|:)9 99ドル0ドル 9
0 9 0 9 0 9 0 9 0
9 9 9 9 9 9 9 9 9
0 9 0 9 0 9 0 9 0
9 9 9 9 9 9 9 9 9
0 9 0 9 0 9 0 9 0
9 9 9 9 9 9 9 9 9
0 9 0 9 0 9 0 9 0
9 9 9 9 9 9 9 9 9
0 9 0 9 0 9 0 9 0

So, now that we have a grid of 9s and 0s we want to generate some random numbers. ? generates a random number from 0 up to (but not including) a given number. Given a list it will generate one random number in this way for each member of the list. So in this case it will generate a number from 0 to 8 for every 9 in the table and a floating point number from 0 to 1 for each 0.

 ?(+.|:)9 99ドル0ドル 9
 0.832573 7 0.926379 7 0.775468 6 0.535925 3 0.828123
 7 0 5 5 4 3 4 5 4
0.0944584 2 0.840913 2 0.990768 1 0.853054 3 0.881741
 3 8 7 0 8 3 3 4 8
 0.641563 4 0.699892 7 0.498026 1 0.438401 6 0.417791
 6 8 7 5 2 3 6 6 3
 0.753671 6 0.487016 4 0.886369 7 0.489956 5 0.902991
 3 4 7 8 1 4 8 0 8
0.0833539 4 0.311055 4 0.200411 6 0.247177 5 0.0464731

But we want numbers from 1 to 9 not 0 to 8. So we add 1.

 (1+?)(+.|:)9 99ドル0ドル 9
 1.4139 4 1.7547 7 1.67065 4 1.52987 1 1.96275
 2 8 2 4 3 9 6 9 9
1.15202 7 1.11341 5 1.0836 1 1.24713 2 1.13858
 9 3 3 2 4 7 3 8 6
1.06383 9 1.67909 4 1.09801 8 1.4805 6 1.0171
 9 5 5 5 9 5 9 4 3
1.22819 1 1.85259 4 1.95632 6 1.33034 3 1.39417
 4 2 5 1 3 7 2 5 6
1.06572 5 1.9942 5 1.78341 5 1.16516 6 1.37087

This is very nice but we've lost the zeroes that I want, so we'll multiply it by the original mask after turning all the nines into ones. I do this by checking if the value is greater than 1. That gives us: (1&<*1+?).
There are a couple of things going on here:

  • We've created a fork which allows us to pack a lot of work into very few characters.
  • We've bonded (&) the 1 to the < verb.

So all combined the (1&<*1+?) is generating random numbers, and zeroing all the numbers which where generated by zeroes in the original grid.

 (1&<*1+?)(+.|:)9 99ドル0ドル 9
0 3 0 2 0 7 0 1 0
9 5 2 7 7 1 4 5 7
0 6 0 8 0 3 0 1 0
4 8 7 5 9 7 7 9 4
0 9 0 6 0 9 0 9 0
6 1 2 1 4 6 8 9 4
0 3 0 8 0 6 0 6 0
2 5 2 2 2 2 3 9 3
0 9 0 3 0 5 0 3 0

The next bit is the (in my opinion, anyway :-) clever bit.
The cut ;. verb has a form x u;._3 y which cuts the input into boxes described by x, and then applies the verb u to them. In this case we have 3 3(4&{++/*0=4&{)@,;._3.

  • The 3 3 is describing the boxes we want - 3x3.
  • The (4&{++/*0=4&{)@, is a verb train which describes what we want to do to each box.

To demonstrate the ;. verb I'll use < to show each box:

 3 3(<);._3(1&<*1+?)(+.|:)9 99ドル0ドル 9
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│0 8 0│8 0 7│0 7 0│7 0 4│0 4 0│4 0 3│0 3 0│
│9 1 3│1 3 2│3 2 3│2 3 8│3 8 5│8 5 5│5 5 9│
│0 6 0│6 0 1│0 1 0│1 0 2│0 2 0│2 0 4│0 4 0│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│9 1 3│1 3 2│3 2 3│2 3 8│3 8 5│8 5 5│5 5 9│
│0 6 0│6 0 1│0 1 0│1 0 2│0 2 0│2 0 4│0 4 0│
│7 1 6│1 6 7│6 7 1│7 1 2│1 2 1│2 1 6│1 6 1│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│0 6 0│6 0 1│0 1 0│1 0 2│0 2 0│2 0 4│0 4 0│
│7 1 6│1 6 7│6 7 1│7 1 2│1 2 1│2 1 6│1 6 1│
│0 7 0│7 0 5│0 5 0│5 0 9│0 9 0│9 0 7│0 7 0│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│7 1 6│1 6 7│6 7 1│7 1 2│1 2 1│2 1 6│1 6 1│
│0 7 0│7 0 5│0 5 0│5 0 9│0 9 0│9 0 7│0 7 0│
│7 9 9│9 9 7│9 7 1│7 1 9│1 9 4│9 4 9│4 9 5│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│0 7 0│7 0 5│0 5 0│5 0 9│0 9 0│9 0 7│0 7 0│
│7 9 9│9 9 7│9 7 1│7 1 9│1 9 4│9 4 9│4 9 5│
│0 3 0│3 0 2│0 2 0│2 0 7│0 7 0│7 0 9│0 9 0│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│7 9 9│9 9 7│9 7 1│7 1 9│1 9 4│9 4 9│4 9 5│
│0 3 0│3 0 2│0 2 0│2 0 7│0 7 0│7 0 9│0 9 0│
│3 1 6│1 6 1│6 1 7│1 7 6│7 6 8│6 8 9│8 9 9│
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│0 3 0│3 0 2│0 2 0│2 0 7│0 7 0│7 0 9│0 9 0│
│3 1 6│1 6 1│6 1 7│1 7 6│7 6 8│6 8 9│8 9 9│
│0 9 0│9 0 3│0 3 0│3 0 4│0 4 0│4 0 3│0 3 0│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘

Some things to notice:

  • The boxes overlap - the second and third columns in the top left box are the first and second in the box to the right of it.
  • There are 7x7 boxes. That's why we had a 9x9 grid initially.
  • Each place we require a sum has a 0 at the box's centre.

Now we just need to either pass the value at the centre back (if it's non-zero) or sum the numbers in the 3x3 box (if the centre is zero).
To do this we need easy access to the centre number. , helps here. It turns the 3x3 grid into a list of 9 items with the centre number at number 4.
4&{ will use { to pull out the centre value and then compare it with 0: 0=4&{. This returns a 0 or 1 for true or false, which we then multiply by the sum +/. If it was zero at the centre we now have our sum as required. If it was not we have zero, so to finish off we just add the centre value 4&{+.
This gives the verb train (4&{++/*0=4&{)@,

 3 3(4&{++/*0=4&{)@,;._3(1&<*1+?)(+.|:)9 99ドル0ドル 9
2 6 9 3 7 9 7
3 47 6 51 5 49 5
3 9 9 6 6 2 8
7 48 6 47 1 37 5
5 4 5 7 7 2 6
5 35 3 49 8 51 9
1 6 6 6 7 4 8
answered Sep 1, 2013 at 7:30
\$\endgroup\$
10
  • \$\begingroup\$ Does your one line of code do all that, including generate the random numbers? Reassure me. Just finding it hard to believe. \$\endgroup\$ Commented Sep 1, 2013 at 19:56
  • \$\begingroup\$ Yep, hard as it may be to believe. The random bit is done by the ?. I'll change the explanation to reflect the newest version. \$\endgroup\$ Commented Sep 1, 2013 at 19:59
  • \$\begingroup\$ @DavidCarraher Most verbs in J are either 1 or 2 characters so 47 characters can pack in a lot of work. \$\endgroup\$ Commented Sep 1, 2013 at 20:02
  • \$\begingroup\$ The cutting of a 9x9 box into 7x7 overlapping squares is definitely the clever bit. In less than 10 minutes I've been able to apply it to beat my current GolfScript implementation by 7.5%. \$\endgroup\$ Commented Sep 1, 2013 at 20:57
  • \$\begingroup\$ Oh well, looks like it's back to the drawing board for me. \$\endgroup\$ Commented Sep 1, 2013 at 21:20
5
\$\begingroup\$

Ruby (135 characters)

a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=[0,1,6,7,8].inject{|s,e|s+a[j+e]+a[j-e]};j+=l+2}
a.each_slice(7){|r|puts"%-3s"*7%r}

Sample output

2 1 6 9 4 5 1 
9 34 4 37 2 31 3 
7 2 3 1 8 1 7 
5 42 4 40 2 47 9 
3 9 9 4 9 4 7 
3 44 4 41 2 47 4 
6 9 1 5 7 6 8 

Breakdown

It's not too obvious how this works, so here's a quick breakdown. NOTE: You can probably skip some of these steps and jump to shorter versions more quickly, but I think it's educational enough to see different ways I shaved off characters, especially by spotting patterns in literals to turn 2-digit numbers into 1-digit versions.

Naive version

Unlike the other Ruby solutions that rely on a two-dimensional array, you can (eventually) get a shorter version by starting with a 1-dimensional array and working with offset values, since the patterns repeat.

ary=(0..48).map { rand(9) + 1 }
offsets = [-8,-7,-6,-1,1,6,7,8]
3.times do |i|
 [8,10,12].each do |j|
 ary[j + 14*i] = ary.values_at(*offsets.map { |e| j+14*i + e }).inject(:+)
 end
end
ary.each.with_index do |e,i|
 $> << ("%-3s" % e)
 $> << ?\n if i % 7==6
end

The key principle here is that we're working at index positions 8, 10, 12, just offset by multiples of 14. Positions 8, 10 and 12 are the centers of the 3x3 grids that we're summing up. In the sample output, 34 is position 8, 42 is position 8 + 14*1, etc. We replace position 8 with 34 by positions offset from position 8 by [-8,-7,-6,-1,1,6,7,8] — in other words 34 = sum(ary[8-8], ary[8-7], ..., ary[8+8]). This same principle holds for all the values of [8 + 14*i, 10 + 14*i, 12 + 14*i], since the pattern repeats.

Optimising it

First, some quick optimisations:

  • Instead of 3.times { ... }, and calculating j + 14*i each time, "inline" the positions [8,10,12,22,24,26,36,38,40].
  • The offsets array is used once, so replace the variable with the literal.
  • Replace do ... end with {...} and switch around the printing to $> << foo. (There's a trick here involving puts nil and () == nil.)
  • Shorter variable names.

The code after this is 177 characters:

a=(0..48).map{rand(9)+1}
[8,10,12,22,24,26,36,38,40].each{|j|a[j]=a.values_at(*[-8,-7,-6,-1,1,6,7,8].map{|e|j+e}).inject(:+)}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

For the next reduction, note that the inject doesn't need the offsets array to be in order. We can either have [-8,-7,-6,-1,1,6,7,8] or some other ordering, since addition is commutative.

So first pair up the positives and the negatives to get [1,-1,6,-6,7,-7,8,-8].

Now you can shorten

[1,-1,6,-6,7,-7,8,-8].map { |e| j+e }.inject(:+)

to

[1,6,7,8].flat_map { |e| [j+e, j-e] }

This results in

a=(0..48).map{rand(9)+1}
[8,10,12,22,24,26,36,38,40].each{|j|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+)}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

which is 176 characters.

Shift by 8 and move to differences

The two-character literal values seem like they can be shortened away, so take [8,10,12,22,24,26,36,38,40] and shift everything down by 8, updating j at the start of the loop. (Note that +=8 avoids needing to update the offset values of 1,6,7,8.)

a=(0..48).map{rand(9)+1}
[0,2,4,14,16,18,28,30,32].each{|j|j+=8;a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+)}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

This is 179, which is bigger, but the j+=8 can actually be removed.

First change

[0,2,4,14,16,18,28,30,32]

to an array of differences:

[2,2,10,2,2,10,2,2]

and cumulatively add these values to an initial j=8. This will eventually cover the same values. (We could probably skip straight to this instead of shifting by 8 first.)

Note that we'll also add a dummy value of 9999 to the end of the differences array, and add to j at the end, not the start of the loop. The justification is that 2,2,10,2,2,10,2,2 looks awfully close to being the same 3 numbers repeated 3 times, and by computing j+difference at the end of the loop, the final value of 9999 won't actually affect the output, since there isn't a a[j] call where j is some value over 10000.

a=(0..48).map{rand(9)+1}
j=8
[2,2,10,2,2,10,2,2,9999].each{|l|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+);j+=l}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

With this differences array, the j+=8 is now just j=8, of course, since otherwise we'd repeatedly add 8 too many. We've also changed the block variable from j to l.

So since the 9999 element has no effect on the output, we can change it to 10 and shorten the array.

a=(0..48).map{rand(9)+1}
j=8
([2,2,10]*3).each{|l|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+);j+=l}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

This is 170 characters.

But now the j=8 looks a bit clunky, and you can save 2 characters by shifting [2,2,10] down by 2 to conveniently get an 8 you can use for assignment. This also needs j+=l to become j+=l+2.

a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+);j+=l+2}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

This is 169 characters. A round-about way to squeeze 7 characters, but it's neat.

Final tweaks

The values_at call is actually sort of redundant, and we can inline an Array#[] call. So

a.values_at(*[1,6,7,8].flat_map{|e|[j+e,j-e]}).inject(:+)

becomes

[1,6,7,8].flat_map{|e|[a[j+e],a[j-e]]}.inject(:+)

You can also spot that flat_map + j+e/j-e + inject can be reduced to a more direct summation with an initial 0 in the array.

This leaves you with 152 characters:

a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=[0,1,6,7,8].inject{|s,e|s+a[j+e]+a[j-e]};j+=l+2}
a.map.with_index{|e,i|$><<"%-3s"%e<<(?\nif i%7==6)}

Finally:

  • map.with_index can become each_slice.
  • Change the printing approach.

135:

a=(0..48).map{rand(9)+1}
([0,0,j=8]*3).each{|l|a[j]=[0,1,6,7,8].inject{|s,e|s+a[j+e]+a[j-e]};j+=l+2}
a.each_slice(7){|r|puts"%-3s"*7%r}
answered Sep 2, 2013 at 18:21
\$\endgroup\$
1
  • \$\begingroup\$ You can replace each with map for one byte. \$\endgroup\$ Commented Nov 1, 2017 at 19:27
3
\$\begingroup\$

Python, 132

This doesn't technically satisfy the rules, because the last digits of each number are aligned rather than the first. But I thought I'd share anyway:

import numpy
G=numpy.random.randint(1,10,(7,7))
G[1::2,1::2]=sum(G[i:6+i:2,j:6+j:2]for i in[0,1,2]for j in[0,1,2]if i&j!=1)
print G

Sample output:

[[ 8 9 8 3 8 5 8]
 [ 6 53 4 45 8 53 8]
 [ 8 2 8 1 5 3 8]
 [ 2 40 6 34 1 32 7]
 [ 4 1 9 1 3 3 2]
 [ 4 35 7 35 6 31 1]
 [ 1 7 2 5 2 8 6]]
answered Aug 31, 2013 at 6:43
\$\endgroup\$
3
\$\begingroup\$

Mathematica, 108

s=#-1;;#+1&;g=1+8~RandomInteger~{7,7};Column/@
ReplacePart[g,{i_?EvenQ,j_?EvenQ}:>g〚s@i,s@j〛~Total~2-g〚i,j〛]

result

For prettier output Column/@ can be replaced with TableForm@ at a cost of 2 characters.

answered Aug 31, 2013 at 21:35
\$\endgroup\$
5
  • \$\begingroup\$ Very, very clever.Grid[ReplacePart[ g, {i_?EvenQ, j_?EvenQ} :> g[[s@i, s@j]]~Total~2 - g[[i, j]]]\[Transpose]] gives a cleaner output and saves a couple of characters iff you count Transpose as a single character, which it is in Mathmatica. Btw, Wolfram's OneLinerSubmission template counted 106 characters, 105 with the one character Transpose. \$\endgroup\$ Commented Sep 1, 2013 at 20:15
  • \$\begingroup\$ @DavidCarraher Thanks. The char count is due to unnecessary newline and :> being one symbol, although it's in the private use area of unicode. One could even remove the transpose, since the validity summation rule holds even after transposition. But it seems Grid doesn't align the entries without further options (v8) \$\endgroup\$ Commented Sep 1, 2013 at 23:45
  • \$\begingroup\$ Grid centers the numbers within columns. Technically, that would not satisfy the challenge, but it does look better than having a list appear in the displayed table. \$\endgroup\$ Commented Sep 2, 2013 at 1:34
  • \$\begingroup\$ Very nice. I just spend considerable time creating the same thing, only I used Part and Tuples. Posting soon. \$\endgroup\$ Commented Sep 3, 2013 at 11:34
  • \$\begingroup\$ You could save two characters with this: p=2|4|6;Column/@ReplacePart[g,{i:p,j:p}:>g[[s@i,s@j]]~Total~2-g[[i,j]]] \$\endgroup\$ Commented Sep 3, 2013 at 11:49
3
\$\begingroup\$

GolfScript ((削除) 79 78 72 70 68 66 65 (削除ここまで) 60 chars)

56,{13%5<,~9rand)}%9/`{>3<zip`{>3<(*(+(\{+}*or' '}+7,%n}+7,/

NB This contains a literal tab, which Markdown may well break.

The clever bit is due to Gareth: see his J solution.

Online demo

answered Aug 31, 2013 at 10:26
\$\endgroup\$
3
\$\begingroup\$

R: 114 characters

a=array(sample(1:9,49,r=T),c(7,7))
for(i in 2*1:3){for(j in 2*1:3)a[i,j]=sum(a[(i-1):(i+1),(j-1):(j+1)])-a[i,j]}
a

First line create a 7 by 7 array filled with randomly chosen numbers from 1 to 9 (uniform distribution with replacement, hence r=T which stands for replace=TRUE). Second line, compute sums of 3 by 3 grids, substract center and replace it with the result. Third line print the resulting grid (by default, matrix and array columns are right aligned).

Example output:

 [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 8 5 6 4 3 2 2
[2,] 1 37 6 41 7 38 8
[3,] 5 3 3 3 9 4 3
[4,] 4 31 3 41 3 44 9
[5,] 3 5 5 9 6 7 3
[6,] 3 32 2 40 4 37 5
[7,] 8 2 4 1 9 1 2
answered Sep 3, 2013 at 11:16
\$\endgroup\$
2
\$\begingroup\$

J, (削除) 67 (削除ここまで) 65 bytes

A naïve and verbose solution in J. It is a straightforward implementation of the task.

(+/^:_"2((,&.>/@(<:,],>:)"0)&.>m){0 m}a)(m=.{;~1 3 5)}a=.>:?7 79ドル

First I create a 7 x 7 array of integers between 1 and 9. In fact J's ? verb generates numbers up to its argument, that's why we need to increment each element,>: in J

a=.>:?7 79ドル 
2 8 7 4 4 5 1
4 5 4 1 6 7 9
3 8 3 6 5 3 3
6 8 6 3 7 7 1
7 7 4 4 5 9 9
2 3 6 5 2 2 9
2 2 6 8 8 1 3

I prepare a mask to be used for zeroing of the odd row/col cells, a pairs of odd row/column indices:

m=.{;~1 3 5
┌───┬───┬───┐
│1 1│1 3│1 5│
├───┼───┼───┤
│3 1│3 3│3 5│
├───┼───┼───┤
│5 1│5 3│5 5│
└───┴───┴───┘

The Catalogue verb { combines items from the atoms inside the boxed list

┌─────┬─────┐
│1 3 5│1 3 5│
└─────┴─────┘

to form a catalogue, the 3x3 table of the pairs above

Then I prepare a table of row/col indices to be used for selection of each of the 3x3 subarrays.

s=.(,&.>/@(<:,],>:)"0)&.>m
┌─────────────┬─────────────┬─────────────┐
│┌─────┬─────┐│┌─────┬─────┐│┌─────┬─────┐│
││0 1 2│0 1 2│││0 1 2│2 3 4│││0 1 2│4 5 6││
│└─────┴─────┘│└─────┴─────┘│└─────┴─────┘│
├─────────────┼─────────────┼─────────────┤
│┌─────┬─────┐│┌─────┬─────┐│┌─────┬─────┐│
││2 3 4│0 1 2│││2 3 4│2 3 4│││2 3 4│4 5 6││
│└─────┴─────┘│└─────┴─────┘│└─────┴─────┘│
├─────────────┼─────────────┼─────────────┤
│┌─────┬─────┐│┌─────┬─────┐│┌─────┬─────┐│
││4 5 6│0 1 2│││4 5 6│2 3 4│││4 5 6│4 5 6││
│└─────┴─────┘│└─────┴─────┘│└─────┴─────┘│
└─────────────┴─────────────┴─────────────┘

For each pair in the m array I make a pair of triplets, centered around each number of the m pair:

 ┌─────┬─────┐
 1 3 -> │0 1 2│2 3 4│
 └─────┴─────┘

These pairs of triplets are used by the J From verb {, which can select multiple rows and columns simultaneously. 0 1 2 / 2 3 4 means that I select rows 0, 1 and 2 together with columns 2, 3 and 4, thus selecting the second 3x3 subarray on the top.

Finally, I can use the 7x7 array and the masks to achieve the task: First I use m as a mask to set the corresponding elements to 0:

0 m}a

Then I take all the 3x3 subarrays using s as a selector and find their sums:

+/^:_"2 s{0 m}a

Then I put these numbers back into the starting array.

 (+/^:_"2 s{0 m}a)m}a 
2 8 7 4 4 5 1
4 39 4 39 6 36 9
3 8 3 6 5 3 3
6 44 6 40 7 42 1
7 7 4 4 5 9 9
2 36 6 43 2 46 9
2 2 6 8 8 1 3

Try it online!

answered Nov 1, 2017 at 14:44
\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Unicode), (削除) 32 (削除ここまで) (削除) 31 (削除ここまで) 30 bytesSBCS

-1 byte thanks to @jslip

|a×ばつ+/+/⊢⌺3 3⊢a←?9⌈m←∘.⍱⍨2|⍳7

Try it online!

answered Aug 12, 2018 at 0:18
\$\endgroup\$
2
  • 1
    \$\begingroup\$ ∧/¨~ -> ⍱/¨ \$\endgroup\$ Commented Aug 12, 2018 at 1:28
  • \$\begingroup\$ @jslip Ah, de Morgan's laws. Thanks :) \$\endgroup\$ Commented Aug 12, 2018 at 7:21
1
\$\begingroup\$

Ruby, 207

I shall present my solution first (as I always do):

a=Array.new(7){Array.new(7){rand(9)+1}}
s=[-1,0,1]
s=s.product s
s.slice!4
r=[1,3,5]
r.product(r).map{|x|u=0
s.map{|y|u+=a[x[0]+y[0]][x[1]+y[1]]}
a[x[0]][x[1]]=u}
puts a.map{|x|x.map{|y|y.to_s.ljust 3}.join
answered Aug 31, 2013 at 2:37
\$\endgroup\$
1
\$\begingroup\$

Ruby, 150 characters

v=(a=0..6).map{a.map{rand(9)+1}}
(o=[1,3,5]).map{|i|o.map{|j|v[i][j]=0
(d=[0,-1,1]).map{|r|d.map{|c|v[i][j]+=v[i+r][j+c]}}}}
puts v.map{|r|"%-3d"*7%r}

if the left justification requirement justification is just that ljust would have to be used... well, no. I love Ruby's formatting capabilities.

Do not use Array.new(7){...}. (0..6).map{...} is both shorter and more readable and you get an assignable range for free.

Line #3 inspired by Doorknob's solution.

answered Aug 31, 2013 at 6:57
\$\endgroup\$
1
\$\begingroup\$

GolfScript, 87 chars

49,{.1&7円/1&!|9rand)*}%.7/{[..1>@0\+]zip{{+}*}%);}:^%zip{^~}%]zip{.0=!=}%{' '+3<}%7/n*

There are too many zips in there... (see online)

3 9 9 3 3 9 8 
6 46 2 50 3 39 8 
7 3 7 2 4 7 3 
8 33 9 51 8 49 5 
4 3 9 9 3 9 2 
1 45 9 41 6 33 2 
4 3 6 1 6 1 4 
answered Aug 31, 2013 at 7:49
\$\endgroup\$
1
\$\begingroup\$

J, 58/64/67 characters

0j_1":(70,ドル:70ドル 1){"0 1 |:>v;v-~7 7{.0,.0,3+/\"1]3+/\v=.1+?7 79ドル

While the specification requires the numbers to be left-aligned, there is no requirement to use the decimal notation, so I guess this is valid output:

1.0e0 8.0e0 9.0e0 6.0e0 2.0e0 9.0e0 6.0e0
6.0e0 3.9e1 8.0e0 4.0e1 2.0e0 3.8e1 4.0e0
1.0e0 4.0e0 2.0e0 8.0e0 3.0e0 9.0e0 3.0e0
2.0e0 2.4e1 5.0e0 4.1e1 9.0e0 4.7e1 8.0e0
1.0e0 3.0e0 6.0e0 5.0e0 3.0e0 5.0e0 7.0e0
4.0e0 3.0e1 1.0e0 2.3e1 1.0e0 3.1e1 1.0e0
6.0e0 5.0e0 4.0e0 2.0e0 1.0e0 5.0e0 8.0e0

If right alignment instead of left alignmnent is acceptable, we're at 58 characters

(70,ドル:70ドル 1){"0 1 |:>v;v-~7 7{.0,.0,3+/\"1]3+/\v=.1+?7 79ドル

J's ": (format) has three formatting modes:

  • right-aligned with n digits or with shrink-wrap (default display)
  • left-aligned scientific notation with n digits and m characters total
  • shrinkwrap boxed display with (left/center/right)-(top/middle/bottom) alignment (below, 69 characters)

The most verbose but also most versatile and the only one able to produce the output as per the example is the 8!:2 formatting foreign, which takes a formatting string as its left argument. Also 67 characters:

'l3.'8!:2(70,ドル:70ドル 1){"0 1 |:>v;v-~7 7{.0,.0,3+/\"1]3+/\v=.1+?7 79ドル

Here is the boxed format:

 0 0":<"0(70,ドル:70ドル 1){"0 1 |:>v;v-~7 7{.0,.0,3+/\"1]3+/\v=.1+?7 79ドル
 
 ┌─┬──┬─┬──┬─┬──┬─┐
 │2│6 │5│7 │5│7 │6│
 ├─┼──┼─┼──┼─┼──┼─┤
 │8│40│4│35│9│49│6│
 ├─┼──┼─┼──┼─┼──┼─┤ 
 │6│7 │2│2 │1│9 │6│
 ├─┼──┼─┼──┼─┼──┼─┤
 │8│41│9│35│3│45│7│
 ├─┼──┼─┼──┼─┼──┼─┤
 │3│1 │5│6 │7│8 │4│
 ├─┼──┼─┼──┼─┼──┼─┤
 │7│37│4│45│6│48│8│
 ├─┼──┼─┼──┼─┼──┼─┤
 │8│4 │5│4 │8│1 │6│
 └─┴──┴─┴──┴─┴──┴─┘
answered Aug 31, 2013 at 8:36
\$\endgroup\$
1
\$\begingroup\$

Perl, 117 characters

print$_,++$j%7?$":$/for map{++$i/7&$i%7&1?
eval join"+",@x[map{$i+$_,$i-$_}1,6,7,8]:" $_"}@x=map{1+int rand 9}$i--..48

This is one of those Perl scripts where all but one of the for loops have been collapsed into map calls so that everything can be done in a single statement. Global variables also make some important appearances in this one. I guess what I'm trying to say here is, this program is a bit gross.

Wait, it gets worse: There's a known bug in the script! It has less than a one-in-a-million chance of getting triggered, though, so I haven't gotten around to fixing it yet.

answered Aug 31, 2013 at 20:45
\$\endgroup\$
2
  • \$\begingroup\$ Don't hold out on us, what is the bug? \$\endgroup\$ Commented Sep 1, 2013 at 1:45
  • \$\begingroup\$ Bonus points to the first person who spots it! \$\endgroup\$ Commented Sep 1, 2013 at 2:23
1
\$\begingroup\$

Mathematica, 106 / 100

I came up with something very similar to ssch's code, before seeing it. I am borrowing his idea of using Column. With ASCII only, 106:

s=#-1;;#+1&
a=8~RandomInteger~{7,7}+1
a[[##]]=a[[s@#,s@#2]]~Total~2-a[[##]];&@@@{2,4,6}~Tuples~2
Column/@a

With Unicode characters (as used by ssch), 100:

s=#-1;;#+1&
a=8~RandomInteger~{7,7}+1
a〚##〛=a〚s@#,s@#2〛~Total~2-a〚##〛;&@@@{2,4,6}~Tuples~2
Column/@a
answered Sep 3, 2013 at 11:44
\$\endgroup\$
1
\$\begingroup\$

Excel VBA, 74 bytes

VBE immediate function that outputs to [B2:H9].

[B2:H9]="=IF(ISODD(ROW()*COLUMN()),SUM(A1:C1,A2,C2,A3:C3),INT(RAND()*8)+1)

Sample Output

enter image description here

answered Aug 9, 2018 at 18:51
\$\endgroup\$
1
\$\begingroup\$

Powershell, (削除) 149 (削除ここまで) 148 bytes

-1 byte thanks to @AdmBorkBork. It's cool!

$i=-1
($a=(,1*8+0,1*3)*3+,1*7|%{$_*(1+(Random 9))})|?{++$i;!$_}|%{6..8+1|%{$_,-$_}|%{$a[$i]+=$a[$i+$_]}}
-join($a|%{if(!(++$i%7)){"
"};'{0,3}'-f$_})

Explanation:

$i=-1 # let $i store -1
($a= # let $a is array of random numbers with zero holes
 (,1*8+0,1*3)*3+,1*7| # the one-dimension array equals
 # 1 1 1 1 1 1 1
 # 1 0 1 0 1 0 1
 # 1 1 1 1 1 1 1
 # 1 0 1 0 1 0 1
 # 1 1 1 1 1 1 1
 # 1 0 1 0 1 0 1
 # 1 1 1 1 1 1 1
 %{ # for each element
 $_*(1+(Random 9)) # multiply 0 or 1 element to random digit from 1 to 9
 } # now $a stores values like (* is a random digit from 1 to 9)
 # * * * * * * *
 # * 0 * 0 * 0 *
 # * * * * * * *
 # * 0 * 0 * 0 *
 # * * * * * * *
 # * 0 * 0 * 0 *
 # * * * * * * *
)|?{++$i;!$_ # calc index $i and passthru values == 0 only
}|%{ # for each zero value cell with index $i
 6..8+1|%{ # offsets for the surrounding cells
 # . . .
 # . x +1
 # +6 +7 +8 
 $_,-$_ # add the mirror offsets 
 # -8 -7 -6
 # -1 x +1
 # +6 +7 +8 
 }|%{ # for each offset 
 $a[$i]+=$a[$i+$_] # add surrounding values to the cell
 }
}
 # display the $a
-join(
 $a|%{ # for each value of $a
 if(!(++$i%7)){"`n"} # line break for each 7 cells
 '{0,3}'-f$_ # formatted value of $a with width = 3 char and align right
 }
) # join all values to string
answered Aug 9, 2018 at 13:13
\$\endgroup\$
3
  • 1
    \$\begingroup\$ You can get rid of a byte (a newline) by encapsulating your $a assignment in parens and moving the next line up to make one big line -- ($a=(,1*8+0,1*3)*3+,1*7|%{$_*(1+(Random 9))})|?{++$i;!$_}|%{6..8+1|%{$_,-$_}|%{$a[$i]+=$a[$i+$_]}} \$\endgroup\$ Commented Aug 10, 2018 at 12:50
  • \$\begingroup\$ No. It doesn't work. The array must be fully populated before $a[$i+$_]. So here are two steps. I had several attempts to encapsulate in one pipe. :) \$\endgroup\$ Commented Aug 10, 2018 at 13:10
  • 1
    \$\begingroup\$ It doesn't work if you don't place parens around the assignment. With ($a=(,1*8+0,1*3)*3+,1*7|%{$_*(1+(Random 9))}), $a is fully populated before the next pipeline instance. It should work (at least, it does for me). \$\endgroup\$ Commented Aug 10, 2018 at 13:13
0
\$\begingroup\$

Mathematica (削除) 142 151 172 (削除ここまで) 179

Code

z = (m = RandomInteger[{1, 9}, {7, 7}]; s = SparseArray; o = OddQ; e = EvenQ; i = {1, 1, 1};
(m + ArrayPad[ListCorrelate[{i, i, i}, m] s[{{i_, j_} /; o@i \[And] o@j -> 1}, {5, 5}], 1]
- 2 m s[{{i_, j_} /; e@i \[And] e@j -> 1}, {7, 7}]) // Grid)

Usage

z

m8

answered Aug 31, 2013 at 18:13
\$\endgroup\$
4
  • \$\begingroup\$ You have 0s; the rules say 1-9 \$\endgroup\$ Commented Aug 31, 2013 at 18:29
  • \$\begingroup\$ Thanks. I corrected the data and pics. The functions remain unchanged. \$\endgroup\$ Commented Aug 31, 2013 at 18:43
  • \$\begingroup\$ Also, the numbers are not aligned as specified in the question. \$\endgroup\$ Commented Aug 31, 2013 at 18:44
  • \$\begingroup\$ Mathematica's wordiness (or, more accurately, insistence on using big words) becomes apparent. \$\endgroup\$ Commented Aug 31, 2013 at 19:50
0
\$\begingroup\$

Julia 0.6, 127 (89) bytes

x=rand(1:9,7,7);[x[i,j]=sum(!(0==k==l)*x[i+k,j+l]for k=-1:1,l=-1:1)for i=2:2:7,j=2:2:7]
Base.showarray(STDOUT,x,1<1;header=1<1)

Try it online!

89 bytes using native display, which might be admissible if additional lines can be printed:

×ばつ7 Array{Int64,2}:
6 6 8 2 3 2 3
7 44 5 33 4 23 5
3 8 1 9 1 3 2
4 41 2 37 5 22 2
7 8 8 8 3 4 2
9 53 6 44 7 36 3
7 7 1 9 2 6 9
answered Nov 1, 2017 at 23:21
\$\endgroup\$
0
\$\begingroup\$

Java 10, (削除) 262 (削除ここまで) (削除) 260 (削除ここまで) (削除) 248 (削除ここまで) 239 bytes

v->{int a[][]=new int[7][7],i=49,j,k;for(;i-->0;)a[i/7][i%7]+=Math.random()*9+1;var r="";for(;++i<7;r+="\n")for(j=0;j<7;r+=(k=a[i][j])>9|j++%2<1?k+" ":k+" ")if(i*j%2>0)for(a[i][j]=k=0;k<9;k++)a[i][j]+=k!=4?a[i+k/3-1][j+k%3-1]:0;return r;}

-12 bytes thanks to @ceilingcat.

Explanation:

Try it here.

v->{ // Method with empty unused parameter and String return-type
 int a[][]=new int[7][7], // Integer-matrix with 7x7 zeroes
 i=49,j,k; // Index integers (`i` starting at 49)
 for(;i-->0;) // Loop `i` in the range (49, 0]:
 a[i/7][j%7]+=Math.random()*9+1;
 // Fill the current cell with a random 1..9 integer
 var r=""; // Result-String, starting empty
 for(;++i<7; // Loop `i` in the range [0, 7):
 r+="\n") // After every iteration: append a new-line to the result
 for(j=0;j<7; // Inner loop `j` in the range [0, 7):
 r+= // After every iteration: append the result-String with:
 (k=a[i][j])>9 // If the current number has 2 digits,
 |j++%2<1? // or it's an even column (indices 0/2/4/6)
 k+" " // Append the current number appended with one space
 : // Else:
 k+" ") // Append the current number appended with two spaces
 if(i*j%2>1) // If both indexes `i` and `j` are odd
 for(a[i][j]=k=0; // Reset both the current item and index `k` to 0
 k<9;k++) // Inner loop `k` in the range [0, 9):
 a[i][j]+= // Sum the item at location `i,j` with:
 k!=4? // If `k` is not 4 (the current item itself)
 a[i+k/3-1][j+k%3-1]
 // Sum it with the numbers surrounding it
 : // Else:
 0; // Leave it the same by adding 0
 return r;} // Return the result-String
answered Nov 2, 2017 at 8:27
\$\endgroup\$
1
  • \$\begingroup\$ @ceilingcat Thanks! And I've been able to save a few more bytes with var instead of String and +=Math.random()*9+1; instead of =(int)(Math.random()*9+1);. It's actually pretty useful for you to visit all my old answers, haha! :D \$\endgroup\$ Commented Nov 26, 2019 at 10:10

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.