平方随机对称


18

挑战

编写返回或打印平方随机对称矩阵的程序或函数。


输入值

N:矩阵的大小,即6 x 6


输出量

矩阵。您可以打印它,将其作为字符串(带有换行符)或作为列表/数组的列表/数组返回。


规则

  1. 您需要至少使用N不同的字符,其中N是方阵(输入)的大小。由于我们仅使用字母[a,z] [A,Z]和数字[0,9](当时仅使用1个数字),因此可以假定N < 27and N > 2,这是因为在那时N <= 2您不能同时拥有两个字母和数字。最后但并非最不重要的一点是,每个字母/数字的发生概率都必须为非零(不必均匀分配)。但是,结果必须至少具有N不同的字母/数字。

  2. 矩阵必须水平和垂直对称。

  3. 恰好2行2列必须严格包含一个个位数(它的位置也应该是随机的)。其余的行/列将仅包含字母。将字母视为[a,z]和[A,Z],当然将一位数字视为[0,9]。

  4. 只是要更容易,你可以假设信件的情况下无所谓,只要案件是对称的意思是:a=A, b=B, etc

  5. 每个可能的输出都必须具有非零的发生概率。随机分布不需要是统一的。


输入 8

输出

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

评论不作进一步讨论;此对话已转移至聊天
Mego

Answers:


4

木炭,30字节

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

在线尝试!链接是详细版本的代码。如果n始终为偶数,则为23个字节:

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

在线尝试!链接是详细版本的代码。说明:

Nθ

输入n

E⊘θ⭆⊘θ‽β

创建nn2个随机小写字母数组。这隐式打印为正方形。n2

J‽⊘θ‽⊘θ

跳到正方形中的任意位置。

I‽χ

打印一个随机数字。

‖C¬

水平和垂直反射以完成矩阵。


14

R124118字节

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

在线尝试!

在R中,看起来像运算符的东西只是从解析器得到特殊处理的函数。

如果将运算符(如-)重新定义为其他功能,它将保留解析器的特殊处理方式。由于-是前缀和中缀,并且我需要sample同时使用一个参数和两个参数来调用该函数,因此我可以使用

`-`=sample

得到我想要的。

因此,代码-letters被翻译为sample(letters),从而随机地将letters内置。但是j-1转换为sample(j,1)1从向量中随机采样项目1:j

(该sample函数的这种行为取决于参数的数量和第一个参数是什么,这在生产代码中是一个极大的麻烦,因此,我很高兴在这里找到对它的有害性质的充分利用!)

否则,代码只会使所需结果的左上象限,用随机数字(位)替换随机元素(j-1,位),然后将其折叠为所需的对称性。在和需要应对的奇数和偶数的情况。j-10:9-1ij


我希望我可以+2来获得很好的解释,还可以编辑相关的R golfing技巧答案。您可以再保存一些字节
JayCe '18

多么奇妙的解决方案和解释!
J.Doe,

6

Python3,287个字节

我第一次尝试在这里打高尔夫球;我确信有人可以做得更好:

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)

在线尝试!

多亏了HyperNeurtrino,Ourous和Heiteria,它缩减为193个字节(请参阅注释)。但是,TFeld正确指出,多次调用sample不能保证至少使用N不同的字符。

考虑到这些,请尝试使用该新版本,该新版本应确保N每次运行至少具有不同的字符。

Python3,265 260个字节,至少N明显不同的字符

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)

在线尝试!


1
欢迎来到PPCG!您可以打出一些空白。无需在符号,符号和字母之间放置空格。a[:-1][::-1]从根本上等同于a[:-2::-1],你可以导入random作为r代替rn,并且可以将移动for循环到内嵌表达式。在线尝试!
HyperNeutrino '18

2
您可以math使用-(-a // 2)来代替导入,math.ceil(a / 2)基本上使用负数(实际上是上限)来代替负数的floor-div。tio.run/##XY7LagMxDEX3/…–
HyperNeutrino

1
您可以将其降低到236:在线尝试!
Οurous

1
更进一步,在196:在线尝试!
Οurous

1
多个sample()s不能保证您至少得到N不同的字符。我设法得到[['g', 'x', 'x', 'g'], [7, 'x', 'x', 7], [7, 'x', 'x', 7], ['g', 'x', 'x', 'g']]N=4,其中只有3个不同的字符
TFeld

3

APL(雅致经典)45 44 43 40字节

感谢@Adám-1个字节

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

在线尝试!

使用矩阵的(max)及其反射使其对称,因此它偏向字母表的后半部分

该数字是从0 ... 25 mod 10统一选择的,因此它对较低的值有较小的偏差


1
⌊2⍴⍵÷2)?⍵ ⍵⍴26]}⌊⍺⍵÷2)?⍺⍵⍴26]}⍨
亚当

@Adám聪明!
ngn

是的,我刚刚意识到。
亚当

如果我没记错的话,可以更改⌊⍺⍵÷2⍺⍵
亚当

@Adám我不能-如果N为奇数,数字可能会居中,并且只能包含1行/列
ngn

3

Japt,31个字节(固定数字位置)

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

在线尝试!


Japt,41个字节(随机数字位置)

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

在线尝试!


说明

;                               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

您的数字当前始终插入同一位置。根据挑战,数字的位置也应该是随机的(由于规则4,对于奇数输入,数字的位置不得在中间行和/或列中)。
凯文·克鲁伊森

@KevinCruijssen我不明白挑战在哪里说数字位置也必须是随机的,尽管如此,我还是请OP澄清一下
Luis felipe De jesus Munoz

1
啊,你确实是对的。我在其他所有答案中都看到它是随机的,因此我可能错误地认为它是强制性的。我们将看到OP所说的。我实际上希望允许它修复,这将使我准备好的答案更容易解决该问题。;)
Kevin Cruijssen

2

Python 2,259字节

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]

在线尝试!


直接允许使用整数吗?〜的想法很酷。我也曾想过,但我还没有真正习惯。
Teck-freak

2

05AB1E29 40 38 字节

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

+11个字节可将数字固定在随机位置,同时对于奇数输入仍要牢记规则3。
-2个字节感谢@MagicOctopusUrn更改îï为,ò并更改了位置»

可以在线进行核实一些测试案例

旧的(29 27字节)回答数字始终位于角落的位置:

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

在线尝试验证更多测试用例

说明:

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

您还可以节省2个字节与旧版本,因为它不要求»
Emigna

@Emigna经过OP验证,该职位确实也应该是随机的。由于规则3具有奇数输入,因此固定为+11个字节。>>>可以保留3个字节,因为这ï也是隐式完成的。不幸的是,这不适用于40字节版本,因为它将插入而不是替换。
凯文·克鲁伊森

@MagicOctopusUrn您链接的TIO仍然包含我的29个字节的答案,而不是28个字节,您是否具有正确的链接?至于失败2,则保证输入为3 <= N <= 26
凯文·克鲁伊森

1
@KevinCruijssen,您是对的,我是个白痴,这是我正在研究的那个人:在线尝试!
魔术章鱼缸

@MagicOctopusUrn噢,不知道那位银行家四舍五入。这也节省了我当前的答案!:D并且首先附加一个随机数字,然后再进行混洗也是一种非常聪明的方法。但是不确定它是否100%有效,因为您将始终拥有n字母表的第一个字母,而不是字母表的n随机字母。首先,通过换行符加入,然后再进行镜像,这在我自己中也节省了一个字节。感谢-2个字节!:) PS:通过删除结尾可以在28个字节中保存一个字节}。:)
Kevin Cruijssen

2

C(GCC) 198个 197 196字节

多亏了ceilingcat,节省了2个字节。

#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]);}

在线尝试!

说明:

// 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]);
}

1

JavaScript(ES6),213 209 206字节

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)()

在线尝试!

已评论

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()

1

干净346312字节

明天高尔夫会更多

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

在线尝试!


1

Python 3,197字节

如@Emigna所述,不适用于的奇数值N(我无法正确理解问题)

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

在线尝试!

我确实认为对randint()+ sample()+ 的调用shuffle()太多了,而摆脱就地改组会很棒:)

我很确定这部分(选择字母和数字)可以打更多些。


对于奇数似乎不正确N
Emigna

该死的,我只是假设N永远都是偶数,因为我不知道矩阵是奇数时如何对称!
etene

1
这些是奇数对称矩阵的一些示例。
Emigna '18

好的,谢谢,我还没那样看过!好吧,我想我的答案是毫无价值的。
etene '18

1

Python 2中275个 266字节

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]

在线尝试!

将数组作为字符列表返回。为了满足规则1,我们建立了一个字符池:

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

下一个棘手的问题是规则3:必须精确地在2列和2行中有一个数字;这意味着n,所选择的数字可能不会出现在中间列或中间行中,这很奇怪。由于我们使用两次反射的方形子数组构造数组s,因此可以使用以下方法完成此操作:

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

即,至少洗牌一次;然后,如果n为奇数,则如果数字位于的最后一列或最后一行,则继续循环s


1

Pyth,48个字节

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

在这里在线尝试。

程序分为三部分-回文功能的定义,数值的选择和主要功能。

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

使用多个随机组合的字母应确保唯一字符的数量始终大于输入数字。


1

Python 2 / Python 3,227字节

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:]

松开一点:

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

以下是较旧的,几乎正确的版本:

Python2,Python3、161字节

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)

似乎N个不同的元素几乎都没有保证。

Python 2 / Python 3,170个字节

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:]

看来我忘记了规则3。[:n * n]也以某种方式滑入。


您的答案在构造对称矩阵的方式上非常聪明,但您不满意规则3(因为结果中没有数字)或规则5(例如,如果n = 3,则永远不会包含a 'z',因此并非所有输出都是可能的)。
Chas Brown '18

好吧,给我泡菜...你是正确的@ChasBrown!好吧,[:n * n]是另一种方法的剩余部分,坦率地说,它不应该存在。但是您对规则三是正确的。我必须纠正它。给我一点
Teck-freak

在这里尝试过您的解决方案,但是出现索引错误...顺便说一句,在PPCG上,TryItOnline非常方便!(另外,这个问题比我最初想的要棘手得多。)
Chas Brown

我随便跑了超过10000次,没有任何错误。
Teck-freak's

找到了。缺少“:”。我直接从脚本中复制了它,但是它一定已经丢失了。应该是“ ...:-1] [N%2:] for i ...”而不是“ ...:-1] [N%2] for i ...”。
Teck-freak's
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.