Square-Random-Symmetrical

18

2

Challenge

Write a program or a function that returns or prints a square-random-symmetrical matrix.


Input

N: The size of the matrix i.e 6 x 6


Output

The matrix. You can either print it, return it as string (with the newlines) or as a list/array of lists/arrays.


Rules

  1. You need to use at least N different characters, where N is the size of the square matrix (input). Since we 're using only letter [a, z][A, Z] and digits [0, 9] (and only 1 digit at the time) you can assume that N < 27 and N > 2, that is because at N <= 2 you can't have both letters and digits. Last but not least, every letter/digit must have non-zero probability of occurring (uniform distribution is not a necessity). However, the result must have at least N different letter/digits.

  2. The matrix has to be both horizontally and vertically symmetrical.

  3. Exactly 2 rows and 2 columns must contain strictly one single-digit number (it's position should be random as well). The rest of rows/cols will contain only letters. Consider letters as [a, z] and [A, Z] and of course single-digit numbers as [0, 9].

  4. Just to be easier, you can assume that the case of the letters doesn't matter, as long as the cases are symmetrical which means: a=A, b=B, etc.

  5. Every possible output must have a non-zero probability of occurring. The random distribution doesn't need to be uniform.


Example

Input: 8

Output:

c r p s s p r c
r k o z z o k r
u t 2 a a 2 t u
y n q z z q n y
y n q z z q n y
u t 2 a a 2 t u
r k o z z o k r
c r p s s p r c

DimChtz

Posted 2018-08-29T20:54:46.433

Reputation: 916

Comments are not for extended discussion; this conversation has been moved to chat.

– Mego – 2018-08-31T02:30:04.467

Answers

4

Charcoal, 30 bytes

NθE⊘⊕θ⭆⊘⊕θ‽βJ‽⊘θ‽⊘θI‽χ‖OO→↓﹪θ²

Try it online! Link is to verbose version of code. If n is always even, then for 23 bytes:

NθE⊘θ⭆⊘θ‽βJ‽⊘θ‽⊘θI‽χ‖C¬

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

Nθ

Input \$ n \$.

E⊘θ⭆⊘θ‽β

Create an \$ \frac n 2 \$ by \$ \frac n 2 \$ array of random lowercase letters. This prints implicitly as a square.

J‽⊘θ‽⊘θ

Jump to a random position in the square.

I‽χ

Print a random digit.

‖C¬

Reflect horizontally and vertically to complete the matrix.

Neil

Posted 2018-08-29T20:54:46.433

Reputation: 95 035

14

R, 124 118 bytes

function(n,i=(n+1)/2,j=n%/%2,m="[<-"(matrix(-letters,i,i),j-1,j-1,0:9-1))cbind(y<-rbind(m,m[j:1,]),y[,j:1])
`-`=sample

Try it online!

In R, things that look like operators are just functions that get special treatment from the parser.

If you redefine an operator (like -) to be some other function, it keeps the special treatment from the parser. Since - is both prefix and infix, and I need to call the sample function with both one and two arguments, I can use

`-`=sample

to get what I want.

So the code -letters is translated to sample(letters), which randomly shuffles the letters built-in. But j-1 is translated to sample(j,1), which randomly samples 1 item from the vector 1:j.

(This behaviour of the sample function depending on the number of parameters and what the first parameter is, is a huge pain in the butt in production code, so I'm happy to find a great use of its perverse nature here!)

Otherwise the code just makes the top left quadrant of the required result, replaces a random element (the j-1,j-1 bit) with a random digit (the 0:9-1 bit), and folds it out for the required symmetry. The i and the j are needed to deal with the even and odd cases.

ngm

Posted 2018-08-29T20:54:46.433

Reputation: 3 974

I wish I could +2 for the great explanation and also editing the related R golfing tip answer. You can save a few more bytes

– JayCe – 2018-08-30T23:44:57.090

What a fantastic solution and explanation! – J.Doe – 2018-08-31T08:57:11.647

6

Python3, 287 bytes

My first try at golfing something here; I'm sure someone can do far better:

import random as rn, math as m
n=int(input())
x,o=m.ceil(n/2),n%2
c=x-1-o
f=lambda l,n: l.extend((l[::-1], l[:-1][::-1])[o])
q=[rn.sample([chr(i) for i in range(97, 123)],x) for y in range(x)]
q[rn.randint(0,c)][rn.randint(0,c)] = rn.randint(0,9)
for r in q:
    f(r, n)
f(q, n)
print(q)

Try it Online!

Thanks to HyperNeurtrino, Ourous and Heiteria this shrunk down to 193 bytes (see comments). However, TFeld correctly pointed out that multiple calls to sample aren't guaranteeing at least N different characters.

That stuff in mind, try this new version that should guarantee at least N different characters per run.

Python3, 265 260 bytes, at least N distinct characters

from random import *
n=int(input())
x=-(-n//2)
o=n%2
c=x+~o
i=randint
u=[chr(j+97)for j in range(26)]
z,q=u[:],[]
for y in [1]*x:
  shuffle(z)
  q+=[z[:x]]
  z=z[x:] if len(z[x:])>=x else u[:]
q[i(0,c)][i(0,c)]=i(0,9)
for r in[q]+q:r.extend(r[~o::-1])
print(q)

Try it online!

souldeux

Posted 2018-08-29T20:54:46.433

Reputation: 259

1

Welcome to PPCG! You can golf a few of the whitespaces out; there's no need to put spaces between symbols and symbols and letters. a[:-1][::-1] is fundamentally equivalent to a[:-2::-1], and you can import random as r instead of rn, and you can move the for loop into an inline expression. Try It Online!

– HyperNeutrino – 2018-08-30T01:56:53.680

2

You can remove the math import by using -(-a // 2) instead of math.ceil(a / 2) which is basically negative floor-div of the negative (effectively ceiling). https://tio.run/##XY7LagMxDEX3/gpvChK1k2YKDRnwlxgv3Hk0Bo9sKy44Xz@Ns2npSroH6XLyvV4Tve972HLiKtnTnDbpb5IFmUAVAuXvCoiiqWQ0aDoeB1T0MojJNH3SSawm@u1z9jIqGuNhaXWhGSDacdQnp6LVw3NDmxyKYiwfbn7LcQE7XRnC6@WMa2IZZKAu8LXA8IFOtSe9/9KGTpTHd5fsam9qQvc/m7/5gqJ3cO8o4wqs6EGg9JG53xTc9x8

– HyperNeutrino – 2018-08-30T01:59:09.380

Very clever thought with the division, thank you! I edited your improvements into my post; I'm new here, so if the way I did that is incorrect I welcome any feedback. Thanks again! – souldeux – 2018-08-30T02:06:56.030

1

You can get it down to 236: Try it online!

– Οurous – 2018-08-30T04:19:09.017

1

Even further, at 196: Try it online!

– Οurous – 2018-08-30T04:58:46.647

1The multiple sample()s don't guarantee that you get at least N different characters. I managed to get [['g', 'x', 'x', 'g'], [7, 'x', 'x', 7], [7, 'x', 'x', 7], ['g', 'x', 'x', 'g']] for N=4, which only has 3 distinct chars – TFeld – 2018-08-30T08:35:04.920

Hm, Good catch @TFeld - I'll need to think on that a bit – souldeux – 2018-08-30T14:19:35.153

By using from random import*, you can save 3 bytes to reach (currently) 193: Try it online!

– Black Owl Kai – 2018-08-30T16:21:59.460

@TFeld Check it out, I've posted an improved version that should make sure we generate at least N distinct characters per run – souldeux – 2018-08-30T20:50:20.667

@souldeux As Heiteira points out, you can remove the space between import and * on the first line to save another byte! – Don Thousand – 2018-09-01T14:39:16.340

3

Japt, 31 bytes (Fixed digit position)

;
/2 c
VÆVÆBö}ÃgT0@Mq9îêUvÃêUv

Try it online!


Japt, 41 bytes (Random digit position)

;
/2 c
VÆVÆBö}ÃgMq´VÉ ,MqVÉ @Mq9îêUvÃêUv

Try it online!


Explanation

;                               Change to new vars
/2 c                            set implicit var V equal to implicit var U / 2 rounded up
VÆVÆBö}ÃgT0@Mq9îêUvÃêUv        Main function

VÆ                              Range from 0 to V and map
  VÆ                            Range from 0 to V and map
    Bö}Ã                        return random char from alphabet
        gT0@                    map upper-left corner
            Mq9Ã                return random number
                ®êUv            horizontal mirror
                    êUv         vertical mirror

Luis felipe De jesus Munoz

Posted 2018-08-29T20:54:46.433

Reputation: 9 639

Your digits are currently always inserted at the same place. Based on the challenge, the position of the digits should be random as well (and may not be in the middle row and/or column for odd inputs due to rule 4). – Kevin Cruijssen – 2018-08-30T11:50:59.037

@KevinCruijssen I dont see where the challenge say the number position must be random as well, I'll ask OP for clarification though – Luis felipe De jesus Munoz – 2018-08-30T11:54:36.137

1Ah, you're indeed right. I saw it's random in all other answer, so I might have falsely assumed it's mandatory. We'll see what OP says. I actually hope fixed it allowed, it would make it a lot easier to fix that problem for my prepared answer.. ;) – Kevin Cruijssen – 2018-08-30T12:03:39.167

3

APL (Dyalog Classic), 45 44 43 40 bytes

thanks @Adám for -1 byte

26{(⎕a,⍺⍴⎕d)[⌈∘⊖⍨⌈∘⌽⍨⍺+@(?⊂⌊⍵÷2)?⍵⍴⍺]},⍨

Try it online!

uses (max) of the matrix with its reflections to make it symmetric, so it's biased towards the latter part of the alphabet

the digit is chosen uniformly from 0...25 mod 10, so it has a small bias to lower values

ngn

Posted 2018-08-29T20:54:46.433

Reputation: 11 449

1⌊2⍴⍵÷2)?⍵ ⍵⍴26]}⌊⍺⍵÷2)?⍺⍵⍴26]}⍨ – Adám – 2018-08-30T08:59:59.597

@Adám clever!­­ – ngn – 2018-08-30T09:06:47.300

Yeah, I just realised. – Adám – 2018-08-30T09:09:12.483

If I'm not mistaken, you can change ⌊⍺⍵÷2⍺⍵. – Adám – 2018-08-30T09:10:00.057

@Adám I can't - if N is odd, the digit might end up in the centre and there'd be only 1 row/column containing it – ngn – 2018-08-30T09:11:00.180

Ah, I didn't think of that. OP could need some test cases. – Adám – 2018-08-30T09:12:26.160

2

Python 2, 259 bytes

from random import*
n=input();c=choice;r=range
w,W=n/2,-~n/2
o=n%2
A=map(chr,r(97,123))
l=[c(r(10))]+sample(A,n)+[c(A)for _ in' '*w*w]
l,e=l[:w*w],l[w*w:W*W]
shuffle(l)
l=[l[w*i:w*-~i]+e[i:i+1]for i in range(w)]+[e[-W:]]
for r in l+l[~o::-1]:print r+r[~o::-1]

Try it online!

TFeld

Posted 2018-08-29T20:54:46.433

Reputation: 19 246

Is using ints directly allowed? Cool idea on the ~ by the way. I was thinking of that too, but I'm not yet really used to it. – Teck-freak – 2018-09-03T17:09:24.433

2

05AB1E, 29 40 38 bytes

A.rs;ò©n∍9ÝΩ®DnαLʒ®%Ā}<Ωǝ®ô»¹Éi.º.∊ëº∊

+11 bytes to fix the digit being at a random position while still keeping rule 3 in mind for odd inputs..
-2 bytes thanks to @MagicOctopusUrn, changing îï to ò and changing the position of the ».

Try it online of verify some more test cases.

Old (29 27 bytes) answer where the digit positions where always in the corners:

A.rs;ò©n∍¦9ÝΩì®ô»¹Éi.º.∊ëº∊

Try it online or verify some more test cases.

Explanation:

A           # Take the lowercase alphabet
 .r         # Randomly shuffle it
            #  i.e. "abcdefghijklmnopqrstuvwxyz" → "uovqxrcijfgyzlbpmhatnkwsed"
s           # Swap so the (implicit) input is at the top of the stack
 ;          # Halve the input
            #  i.e. 7 → 3.5
  ò         # Bankers rounding to the nearest integer
            #  i.e. 3.5 → 4
   ©        # And save this number in the register
    n       # Take its square
            #  i.e. 4 → 16
     ∍      # Shorten the shuffled alphabet to that length
            #  i.e. "uovqxrcijfgyzlbpmhatnkwsed" and 16 → "uovqxrcijfgyzlbp"
9ÝΩ         # Take a random digit in the range [0,9]
            #  i.e. 3
   ®Dnα     # Take the difference between the saved number and its square:
            #  i.e. 4 and 16 → 12
       L    # Create a list in the range [1,n]
            #  i.e. 12 → [1,2,3,4,5,6,7,8,9,10,11,12]
ʒ   }       # Filter this list by:
 ®%Ā        #  Remove any number that's divisible by the number we've saved
            #   i.e. [1,2,3,4,5,6,7,8,9,10,11,12] and 4 → [1,2,3,5,6,7,9,10,11]
     <      # Decrease each by 1 (to make it 0-indexed)
            #  i.e. [1,2,3,5,6,7,9,10,11] → [0,1,2,3,5,6,7,9,10]
      Ω     # Take a random item from this list
            #  i.e. [0,1,2,3,5,6,7,9,10] → 6
       ǝ    # Replace the character at this (0-indexed) position with the digit
            #  i.e. "uovqxrcijfgyzlbp" and 3 and 6 → "uovqxr3ijfgyzlbp"
®ô          # Split the string into parts of length equal to the number we've saved
            #  i.e. "uovqxr3ijfgyzlbp" and 4 → ["uovq","xr3i","jfgy","zlbp"]
  »         # Join them by new-lines (this is done implicitly in the legacy version)
            #  i.e. ["uovq","xr3i","jfgy","zlbp"] → "uovq\nxr3i\njfgy\nzlbp"
   ¹Éi      # If the input is odd:
            #  i.e. 7 → 1 (truthy)
      .º    # Intersect mirror the individual items
            #  i.e. "uovq\nxr3i\njfgy\nzlbp"
            #   → "uovqvou\nxr3i3rx\njfgygfj\nzlbpblz"
        .∊  # And intersect vertically mirror the whole thing
            #  i.e. "uovqvou\nxr3i3rx\njfgygfj\nzlbpblz"
            #   → "uovqvou\nxr3i3rx\njfgygfj\nzlbpblz\njfgygfj\nxr3i3rx\nuovqvou"
  ë         # Else (input was even):
   º∊       #  Do the same, but with non-intersecting mirrors

Kevin Cruijssen

Posted 2018-08-29T20:54:46.433

Reputation: 67 575

You could also save 2 bytes with the legacy version since it doesn't require » – Emigna – 2018-08-30T13:17:37.633

@Emigna Verified with OP, and the position should indeed be random as well. Fixed for +11 bytes due to rule 3 with odd inputs.. >.> And 3 bytes could have been saved in the legacy because the ï was done implicitely as well. Unfortunately this doesn't apply to the 40-byte version because would insert instead of replace. – Kevin Cruijssen – 2018-08-30T14:50:33.697

@MagicOctopusUrn The TIO you linked still contained my 29 bytes answer instead of 28, do you have the correct link? As for the failing for 2, the input is guaranteed to be 3 <= N <= 26. – Kevin Cruijssen – 2018-08-30T15:32:02.223

1

@KevinCruijssen you're right, I'm a moron, here's the one I was working out: Try it online!

– Magic Octopus Urn – 2018-08-30T15:36:29.320

@MagicOctopusUrn Oh, didn't knew about that bankers rounding. That saves a byte in my current answer as well! :D And first appending a random digit and only then shuffling is a pretty smart approach as well. Not sure if it's 100% valid though, since you will always have the first n letters of the alphabet, instead of n random letters of the alphabet. And first joining by newlines and only then doing the mirrors saves a byte as well in mine. Thanks for -2 bytes! :) PS: One byte can be saved in your 28-byter by removing the trailing }. :) – Kevin Cruijssen – 2018-08-30T15:43:02.653

2

C (gcc), 198 197 196 bytes

Saved 2 bytes thanks to ceilingcat.

#define A(x)(x<n/2?x:n-1-x)
#define R rand()
S(n,x,y){int s[x=n*n];for(srand(s),y=R;x;)s[x]=97+(--x*31+y)%71%26;y=n/2;for(s[R%y+n*(R%y)]=48+R%10;x<n*n;++x%n||puts(""))putchar(s[A(x%n)+A(x/n)*n]);}

Try it online!

Explanation:

// Coordinate conversion for symmetry
#define A (x) (x < n / 2 ? x : n - 1 - x)
// Get a random and seed
#define R rand()

S (n, x, y)
{
   // the array to store matrix values (x is the array size)
   // Note that we do not need the whole array, only its first quarter
   int s[x = n * n];

   // iterate n*n-1 times until x is zero
   for (srand(s), y = R; x;)
       // and fill the array with pseudo-random sequence of letters
       s[x] = 97 + (--x * 31 + y) % 71 % 26;

   // this is the max. coordinate of the matrix element where a digit may occur
   y = n / 2;

   // drop a random digit there
   s[R % y + n * (R % y)] = 48 + R % 10;

   // Now we output the result. Note that x is zero here
   for (; 
       x < n * n; // iterate n*n times
       ++x % n || puts ("") // on each step increase x and output newline if needed
       )
       // output the character from the array
       putchar (s[A (x % n) + A (x / n) * n]);
}

Max Yekhlakov

Posted 2018-08-29T20:54:46.433

Reputation: 601

1

Clean, 346 312 bytes

will golf more tomorrow

import StdEnv,Data.List,Math.Random,System.Time,System._Unsafe
$n#q=twice(transpose o\q=zipWith((++)o reverse o drop(n-n/2*2))q q)[[(['a'..'z']++['0'..'9'])!!(c rem 36)\\c<-genRandInt(toInt(accUnsafe(time)))]%(i*n/2,i*n/2+(n-1)/2)\\i<-[1..(n+1)/2]]
|length(nub(flatten q))>=n&&sum[1\\c<-q|any isDigit c]==2=q= $n

Try it online!

Οurous

Posted 2018-08-29T20:54:46.433

Reputation: 7 916

1

JavaScript (ES6), 213 209 206 bytes

n=>(a=[],F=(x=y=d=c=0,R=k=>Math.random()*k|0,g=y=>(r=a[y]=a[y]||[])[x]=r[n+~x]=v.toString(36))=>y<n/2?F(g(y,R[v=R(m=~-n/2)<!d&x<m&y<m?R(d=10):R(26)+10]=R[v]||++c,g(n+~y))&&++x<n/2?x:+!++y,R):!d|c<n?F():a)()

Try it online!

Commented

n => (                             // n = input
  a = [],                          // a[][] = output matrix
  F = (                            // F = main recursive function taking:
    x = y =                        //   (x, y) = current coordinates
    d = c = 0,                     //   d = digit flag; c = distinct character counter
    R = k =>                       //   R() = helper function to get a random value in [0,k[
      Math.random() * k | 0,       //         also used to store characters
    g = y =>                       //   g() = helper function to update the matrix
      (r = a[y] = a[y] || [])[x]   //         with horizontal symmetry
      = r[n + ~x] = v.toString(36) //         using the base-36 representation of v
  ) =>                             //
    y < n / 2 ?                    // if we haven't reached the middle row(s) of the matrix:
      F(                           //   do a recursive call to F():
        g(                         //     invoke g() ...
          y,                       //       ... on the current row
          R[v =                    //       compute v = next value to be inserted
            R(m = ~-n/2) < !d &    //       we may insert a digit if no digit has been
            x < m &                //       inserted so far and the current coordinates are
            y < m ?                //       compatible: 2 distinct rows / 2 distinct columns
              R(d = 10)            //         if so, pick v in [0, 9] and update d
            :                      //       else:
              R(26) + 10           //         pick v in [10, 35] for a letter
          ] = R[v] || ++c,         //       set this character as used; update c accordingly
          g(n + ~y)                //       invoke g() on the mirror row
        ) &&                       //     end of outer call to g()
        ++x < n / 2 ?              //     if we haven't reached the middle column(s):
          x                        //       use x + 1
        :                          //     else
          +!++y,                   //       increment y and reset x to 0
        R                          //     explicitly pass R, as it is used for storage
      )                            //   end of recursive call to F()
    :                              // else:
      !d | c < n ? F() : a         //   either return the matrix or try again if it's invalid
)()                                // initial call to F()

Arnauld

Posted 2018-08-29T20:54:46.433

Reputation: 111 334

1

Python 3, 197 bytes

As mentioned by @Emigna, doesn't work for odd values of N (I didn't understand the question properly)

from random import*
def m(N):M=N//2;E=reversed;R=range;B=[randint(48,57),*(sample(R(97,123),N)*N)][:M*M];shuffle(B);r=R(M);m=[k+[*E(k)]for k in[[chr(B.pop())for i in r]for j in r]];m+=E(m);return m

Try it online!

I do think the calls to randint() + sample() + shuffle() are too much, and getting rid of in-place shuffling would be great :)

I'm pretty sure this part (that selects the letters & digit) could be golfed a bit more.

etene

Posted 2018-08-29T20:54:46.433

Reputation: 448

Doesn't seem correct for odd N. – Emigna – 2018-08-30T13:50:11.927

Damn, I had just assumed N would always be even since I don't get how the matrix could be symmetrical if it's odd ! – etene – 2018-08-30T13:51:52.233

1These are some examples of odd symmetrical matrices. – Emigna – 2018-08-30T13:57:04.870

Okay, thanks, I hadn't seen it that way ! Well I guess my answer is worthless as is then. – etene – 2018-08-30T13:59:48.483

1

Python 2/Python 3, 227 bytes

from random import*
def m(N):n=N-N//2;r=range;C=choice;c=n*[chr(i+97)for i in r(26)];shuffle(c);c[C([i for i in r(n*(N-n))if(i+1)%n+1-N%2])]=`C(r(10))`;R=[c[i*n:i*n+n]+c[i*n:i*n+n-N%2][::-1]for i in r(n)];return R+R[::-1][N%2:]

ungolfing a bit:

from random import * # get 'choice' and 'shuffle'
def matrix(N):
    n = ceil(N/2) # get the size of the base block
    # get a shuffleable lowercase alphabet
    c = [chr(i+97)for i in range(26)]
    c = n*c # make it large enough to fill the base-block
    shuffle(c) # randomize it
    digit = choice('1234567890') # get random digit string
    ## this is only needed as to prevent uneven side-length matrices
    #  from having centerline digits.
    allowed_indices = [i for i in range( # get all allowed indices
        n*(N-n)) # skip those, that are in an unmirrored center-line
        if(i+1)%n  # only use those that are not in the center column
                 +1-N%2] # exept if there is no center column
    index = choice(allowed_indices) # get random index
    c[index]=digit # replace one field at random with a random digit
    ## 
    R=[]
    for i in range(n):
        r = c[i*n:i*n+n] # chop to chunks sized fit for the base block
        R.append(r+r[::-1][N%2:]) # mirror skipping the center line
    return R+R[::-1][N%2:] # mirror skipping the center line and return

Older, almost correct versions below:

Python2, Python3, 161 bytes

from random import *
N=26
n=N-N//2
c=[chr(i+97)for i in range(26)]
R=[ r+r[::-1][N%2:]for r in[(shuffle(c),c[:n])[1]for i in range(n)]]
R+=R[::-1][N%2:]
print(R)

It seems N differing elements is only almost guarranteed.

Python 2/Python 3, 170 bytes

from random import*
def m(N):n=N-N//2;r=range;c=n*[chr(i+97)for i in r(26)][:n*n];shuffle(c);R=[_+_[::-1][N%2:]for _ in[c[i*n:i*n+n]for i in r(n)]];return R+R[::-1][N%2:]

It seems I forgot rule 3. Also somehow the [:n*n] slipped in.

Teck-freak

Posted 2018-08-29T20:54:46.433

Reputation: 131

Your answer is very clever in the way it constructs the symmetric matrix, but you have not satisfied rule 3 (as you don't have any digits in your result), nor rule 5 (e.g., if n = 3, you will never have an output containing a 'z', so not every output is possible). – Chas Brown – 2018-09-02T22:30:39.720

Well pickle me and ... you're correct @ChasBrown ! Well, the [:n*n] is a remainder from a different approach and frankly it shouldn't be there. But you're correct about rule three. I'll have to correct it. Give me a bit. – Teck-freak – 2018-09-03T00:57:11.113

Tried your solution here, but there was an index error... BTW, TryItOnline is super handy here at PPCG! (Also, this problem is way trickier than I thought at first...)

– Chas Brown – 2018-09-03T05:01:26.190

I litterally ran it over 10000 times without any error. – Teck-freak – 2018-09-03T15:06:44.820

found it. a ':' was missing. I copied it directly from my script, but it must have gotten lost. it should be "... :-1][N%2:]for i ..." instead of "... :-1][N%2]for i ...". – Teck-freak – 2018-09-03T15:11:18.193

@ChasBrown It is tricky because of the single digit that has to be in precisely two rows and two columns. Otherwise it'd be easy. Thanks for the tip with TIO. I'll keep that in mind. – Teck-freak – 2018-09-03T15:18:39.327

1

Python 2, 275 266 bytes

from random import*
def f(n):
 R=range;C=choice;A=map(chr,R(97,123));b=N=n-n/2;c=`C(R(10))`;s=[c]+sample(A,n-1)+[C(A)for i in R(N*N-n)]
 while b:shuffle(s);i=s.index(c);b=n%2>(i<N*N-N>N-1>i%N)
 a=[r+r[~(n%2)::-1]for r in[s[i::N]for i in R(N)]];return a+a[~(n%2)::-1]

Try it online!

Returns the array as a list of lists of characters. To satisfy Rule 1, we set up a pool of characters:

s = [c]                        # the unique digit...
     + sample(A,n-1)           # then sample without replacement `n-1` chars in a-z, 
                               # so we have `n` distinct chars
     + [C(A)for i in R(N*N-n)] # and fill out the rest with any in a-z

The next tricky bit is rule 3: there must be exactly 2 columns and rows having a digit; this means for n odd, that the chosen digit may not appear in the middle column or middle row. Since we construct the array using a twice reflected square sub array s, that is accomplished here by using:

while b:            # to save a couple bytes, `b` is initialized 
                    # to `N`, which is greater than 0.
    shuffle(s)      # shuffle at least once...
    i = s.index(c)  # c is the unique digit used
    b = n%2 
             >      # if n is even, 0>(any boolean) will be false,
                    # so exit the loop; otherwise n odd, and we are
                    # evaluating '1 > some boolean', which is equivalent 
                    # to 'not (some boolean)'
         (i<N*N-N   # i is not the last column of s...
             >      # shortcut for ' and ', since N*N-N is always > N-1
          N-1>i%N)  # is not the last row of s

i.e., shuffle at least once; and then, if n is odd, keep looping if the digit is in the last column or the last row of s.

Chas Brown

Posted 2018-08-29T20:54:46.433

Reputation: 8 959

1

Pyth, 48 bytes

L+b_<b/Q2JmO/Q2 2jy.eyXWqhJkbeJOT<csm.SGQK.EcQ2K

Try it out online here.

The program is in 3 parts - definition of palindromisation function, choosing location of numeric, and main function.

Implicit: Q=eval(input()), T=10, G=lower case alphabet

L+b_<b/Q2   Palindromisation function
L           Define a function, y(b)
      /Q2   Half input number, rounding down
    <b      Take that many elements from the start of the sequence
   _        Reverse them
 +b         Prepend the unaltered sequence

JmO/Q2 2   Choose numeric location
  O/Q2     Choose a random number between 0 and half input number
 m     2   Do the above twice, wrap in array
J          Assign to variable J

jy.eyXWqhJkbeJOT<csm.SGQK.EcQ2K   Main function
                           cQ2    Divide input number by 2
                         .E       Round up
                        K         Assign the above to K
                    .SG           Shuffle the alphabet
                  sm   Q          Do the above Q times, concatenate
                 c      K         Chop the above into segments of length K
                <             K   Take the first K of the above
  .e                              Map (element, index) as (b,k) using:
       qhJk                         Does k equal first element of J?
      W                             If so...
     X     b                          Replace in b...
            eJ                        ...at position <last element of J>...
              OT                      ...a random int less than 10
                                    Otherwise, b without replacement
    y                               Apply palindromisation to the result of the above
 y                                Palindromise the set of lines
j                                 Join on newlines, implicit print

Using several shuffled alphabets should ensure that the number of unique characters is always more then the input number.

Sok

Posted 2018-08-29T20:54:46.433

Reputation: 5 592