交替模式


16

在一个已删除的stackoverflow问题中,有人发布了以下内容:

编写程序或函数以在给定的整数内*#基于给定的整数打印交替的图案n。一些例子:

输入:n=1
输出:

*

输入n=5
输出:

*####
###**
***##
###**
*####

输入:n=8
输出:

*#######
######**
***#####
####****
****####
#####***
**######
#######*

由于这看起来像是一个很酷的代码挑战,所以就在这里。

这些模式是如何建立的?

第一行以单行开头*,后跟n-1大量#
然后,第二行包含两个*n-2前导量很大#
第三行以3开头*,后跟n-3数量#
等等

到达中间(n/2)后,我们再次以*,可以在上面的示例中看到。

注意,对于奇数输入数字,相反的线对(因此,第一和最后;第二和最后一个等;等等)完全相同。在n=5示例中,第一行和最后一行是*####;第二行和最后一行是###**
然而,对于偶数输入数字,相反的一对线是相反的。在n=8示例中,第一行和最后一行是*##############*; 第二行######**和倒数第二行是和**######; 等等

挑战规则:

  • 您可以使用任意两个不同的可打印字符来代替*#。您可以使用AB; 37; <>; 等等。请在回答中说明您使用过的内容。
  • 您可以假设n将为正整数(>= 1
  • 您可以为每行或2D字符矩阵输出字符串列表/数组,而不是将其打印到STDOUT。

通用规则:

  • 这是,因此最短答案以字节为单位。
    不要让代码高尔夫球语言阻止您使用非代码高尔夫球语言发布答案。尝试针对“任何”编程语言提出尽可能简短的答案。
  • 标准规则适用于您的答案,因此您可以使用STDIN / STDOUT,具有正确参数的函数/方法和返回类型的完整程序。你的来电。
  • 默认漏洞是禁止的。
  • 如果可能的话,请添加一个带有测试代码的链接。
  • 另外,强烈建议为您的答案添加说明。

测试案例(第一n=1n=10

*

*#
#*

*##
#**
*##

*###
##**
**##
###*

*####
###**
***##
###**
*####

*#####
####**
***###
###***
**####
#####*

*######
#####**
***####
###****
***####
#####**
*######

*#######
######**
***#####
####****
****####
#####***
**######
#######*

*########
#######**
***######
#####****
*****####
#####****
***######
#######**
*########

*#########
########**
***#######
######****
*****#####
#####*****
****######
#######***
**########
#########*

您可以使用任何两个不同的字符来代替*和#。 ”-它们必须可打印吗?我们可以使用NUL和SOH(ASCII代码0和1)吗?
ngn

@ngn对不起,仅可打印字符。将在挑战说明中阐明。
凯文·克鲁伊森

Answers:


14

果冻,9字节

>þµoṚUÐeY

在线尝试!

说明

>þ           Create a table of (x>y) over [1…n]×[1…n]:
               [0 1 1 1 1]
               [0 0 1 1 1]
               [0 0 0 1 1]
               [0 0 0 0 1]
               [0 0 0 0 0]
  µ          Take this array, and...
   oṚ        OR it with its reverse:
               [0 1 1 1 1]
               [0 0 1 1 1]
               [0 0 0 1 1]
               [0 0 1 1 1]
               [0 1 1 1 1]
    UÐe      Apply U (reverse) to even-indexed rows.
       Y     Join by newlines.

17

Python 2,62个字节

lambda n:["%*s"%(i%2*2*n-n,"x"*min(i+1,n-i))for i in range(n)]

在线尝试!

用途 x和空间。

行的计算如下:

"%-5s" % "x"      == "x    "
"%5s"  % "xx"     == "   xx"
"%-5s" % "xxx"    == "xxx  "
"%5s"  % "xx"     == "   xx"
"%-5s" % "x"      == "x    "

使用说明%*s符在n和之间进行选择-n



6

MATL,34 31 18字节

:t!>tPY|!"@X@oQ&P!

在MATL Online上尝试

使用0表示*,使用1表示#。基于Lynn的Jelly答案


较早的答案,31个字节:

2/tk:wXk:Ph"X@ot~XHh@Gy-hHQ&PY"

在MATL Online上尝试

使用1表示*,使用0表示#。

         % implicit input, say 5
2/       % divide input number by 2 [2.5]
tk       % make a copy and floor that [2.5, 2]
:        % create range 1 to the floored value [2.5, [1, 2]]
wXk      % bring out the division result and this time ceil it
         %  [[1, 2], 3]
:        % create range 1 to that [[1, 2], [1, 2, 3]]
Ph       % flip the last array and concatenate horizontally 
         %  [[1, 2, 3, 2, 1]]
"        % loop through the array
  X@o    % Is the current loop index odd? 1 for odd, 0 for even
  t~     % duplicate and logical negate that
  XH     % copy that value to clipboard H
  h      % and concatenate the values ([1 0] on odd iterations, [0 1] on even) 
  @      % push current value from array (say 2, then stack is [[0 1], 2)
  G      % push input again
  y-     % subtract current array value from input [[0 1], 2, 3]
  h      % concatenate those two [[0 1], [2, 3]]
  H      % get the stored value from clipboard H (1 for even iterations, 0 for odd) 
  Q      % increment that
  &P     % flip the array in that dimension: in even iterations, this flips
         %   across columns and hence inverts the two values. [[0 1], [3, 2]]
         %   in odd iterations, it's a no-op
  Y"     % run-length decoding - repeat the element from first array the number of times
         %  specified in the second array
         % implicit loop end, implicit output

6

APL(Dyalog Classic),18字节

a[↑⊢∘⌽\(⊂>⊢⌊⌽)⍳⎕]

在线尝试!

输出AB代替*#

评估输入n

⍳⎕ 向量 0 1 ... n-1

⊢⌊⌽他们()和反向()之间的min()-请参阅火车

⊂>⊢⌊⌽整体上的向量()是否小于其每个⊢⌊⌽向量-返回布尔(0/1)向量的向量

⊢∘⌽\ 反转所有其他向量

混合成矩阵

⎕a大写英文字母,'AB...Z'

⎕a[ ]替换0 1'A' 'B'


出于好奇。仅输出不带空格的0和1矩阵将是多少个字节?我假设⎕a[...}他们转换为AB不带空格比让他们更短0,并1没有考虑到你使用的空间,但只是好奇,如果有字节太大的区别,如果你让他们为01
凯文·克鲁伊森

1
@KevinCruijssen据我所知,打高尔夫球的长度是相同的⎕d[-... ]⊃¨⍕¨...在后面的表达式中⍕¨是“格式化每个”-将每个数字转换为嵌套的char 向量,因此我们需要“首先每个” “(⊃¨)仅获得char 标量(因此在打印时无空格)。
ngn

5

木炭,21字节

≔⮌…⁰NθEθ⭆蛧⟦μλ⟧κ⌊⟦κι

在线尝试!用途01。链接是冗长的代码版本,§*#其中包括将输出转换为*#的问题。说明:

    N                   Input number
  …⁰                    Range from 0
 ⮌                      Reversed
≔    θ                  Assign to `q`
      Eθ                Map over reversed range
        ⭆θ              Map over reversed range and join
           §⟦μλ⟧κ       Alternate between range and reversed range column
                 ⌊⟦κι   Minimum of range and reversed range row
          ›             Greater
                        Implicitly print each row on its own line

5

果冻 12  15 字节

+3修复n=1边缘错误:(

R«Ṛ$‘r⁸ṬUÐe0YE?

一个完整的程序接受它打印在使用OP定义的输出的整数01用于*#分别。

在线尝试!

怎么样?

R«Ṛ$‘r⁸ṬUÐe0YE? - Main Link: integer, n
R               - range -> [1,2,3,4,...,n]
   $            - last two links as a monad:
  Ṛ             -   reverse -> [n,...,4,3,2,1]
 «              -   minimum (vectorises) -> [1,2,3,4,...,4,3,2,1]
    ‘           - increment (vectorises) -> [2,3,4,5,...,5,4,3,2]
      ⁸         - chain's left argument, n
     r          - inclusive range (vectorises) -> [[2,3,...,n],[3,4,...n],[4,5,...n],[5,...n],...,[5,...n],[4,5,...n],[3,4,...n],[2,3,...,n]]
       Ṭ        - untruth (vectorises) -> [[0,1,1,...,1],[0,0,1,1,...,1],[0,0,0,1,...,1],[0,0,0,0,1,...,1],...,[0,0,0,0,1,...,1],[0,0,0,1,...,1],[0,0,1,1,...,1],[0,1,1,...,1]]
         Ðe     - apply to entries with even indices:
        U       -   upend              -> [[0,1,1,...,1],[1,1,...,1],[0,0,0,1,...,1],[1,...,1,0,0,0,0],...]
              ? - if...
             E  - ...condition: all equal? (only true when n=1, where we have [1,1])
           0    - ...then: zero
            Y   - ...else: join with newline characters
                - implicit print

看起来这完全是我的算法,但是是另一种实现,它输出0而不是1,反之亦然。
暴民埃里克(Erik the Outgolfer)'18年

是的,实际上是同一件事……而且我没有更新我的帖子以显示我所做的修复。
乔纳森·艾伦,


4

Java 10,145个字节

n->{var r=new char[n][n];for(int j=0,k;j<n;++j)for(k=0;k<n;)r[j][k]=k++<(j<n/2?j%2<1?j+1:n+~j:j%2>0?j:n-j)?j%2<1?'*':'#':j%2>0?'*':'#';return r;}

所有的三进制都使它有些混乱,但是效果很好。我尝试展平嵌套循环和其他各种方法,但是它们只会增加字节数。在这里在线尝试。

取消高尔夫:

n -> { // lambda taking an integer as output and returning a char[][]
    var r = new char[n][n]; // the output array; we make use of Java 10's var here (replace with char[][] for another 4 bytes to make this work in Java 8)
    for(int j = 0, k; j < n; ++j) // iterate over the lines
        for(k = 0; k < n; )       // iterate over the j'th line
            r[j][k] = // set the current character
                      k++ < // determine if we're in the first or second portion of the line:
                            (j < n/2 ? // for the first half of the output:
                                 j%2 < 1  // on even lines ...
                                 ? j + 1  // ... print the first symbol j+1 times ...
                                 : n + ~j // ... on odd lines, print it n-j-1 times.
                             : j%2 > 0 ?  // for the second half of the output, on odd lines ...
                                 j :      // ... print the first symbol j times ...
                                 n - j)   // ... on even lines, print it n-j times.
                      ? j%2 < 1 ? '*' : '#'  // for the first part of the line, use '*' on even lines, '#' otherwise
                      : j%2 > 0 ? '*' : '#'; // for the second part of the line, use '*' on odd lines, '#' otherwise
    return r; // return the completed array
}

Java的8 11,179个 127字节

n->{String r="",a,b;for(int j=0;j<n;b="#".repeat(j<n/2?n+~j:j),r+=(j++%2<1?a+b:b+a)+"\n")a="*".repeat(j<n/2?j+1:n-j);return r;}

在此处在线尝试(TIO还没有Java 11,因此它使用了一种自定义方法,其结果与String#repeat())。

感谢Kevin Cruijssen高尔夫球了52个字节!

取消高尔夫:

n -> { // lambda taking an int argument and returning a String
    String r = "", // the output String
           a,      // temporary String containing the '*'s
           b;      // temporary String containing the '#'s
    for(int j = 0; j < n; // loop over the lines
        b = "#".repeat( // repeat the '#' character ...
            j < n/2 ? n + ~j // ... n-j-1 times in the first half of the output ...
            : j), // ... j times in the second half
        r += (j++ % 2 < 1 ? a + b : b + a) + "\n") // assemble the j'th line and append it to the output: on even lines, the '*'s go first; on odd lines, the '#'s go first
        a = "*".repeat( // repeat the '*' character ...
              j < n/2 ? j + 1 // ... j+1 times in the first half of the output ...
              : n - j); // n-j times in the second half
    return r; // return the completed output
}

3
如果您更改为Java 11,则可以通过使用"*".repeat(...)"#".repeat(...)(以及返回一个String而不是直接打印并将其打高尔夫球n-j-1n+~j)将其打高尔夫球至127个字节:n->{String r="",a,b;for(int j=0;j<n;b="#".repeat(j<n/2?n+~j:j),r+=(j++%2<1?a+b:b+a)+"\n")a="*".repeat(j<n/2?j+1:n-j);return r;}
Kevin Cruijssen

谢谢,这节省了很多字节。我已经设法使用嵌套循环为Java 10创建了145字节的版本–等不及Java 11的发布,这种repeat()方法确实非常适合打高尔夫球。
OOBalance

4

Lua 148133 字节

function(n)t,a,b={},".","#"for i=1,n do r=i<n/2+1 and i or-~n-i s=a:rep(r)..b:rep(n-r)t[i]=i%2<1 and s:reverse()or s end return t end

在线尝试!

-15个字节,感谢@KevinCruijssen和@JoKing。

function(n)
   t = {}; a = "."; b = "#"          -- initialize variables, output is in table
                                     -- strings are needed in variables for
                                     --   the str:rep and str:reverse syntax

   for i = 1, n do                          -- build the rows of the table
      r = i<=(n+1)/2 and i or n-i+1         -- logic used to count up then down
      str = a:rep(r)..b:rep(n-r)            -- append correct number of '.'s, fill
                                            --   in the rest with '#'s
      t[i]=i%2==0 and str:reverse() or str  -- logic used to control reversing
   end
   return t                                 -- return table
end

2
我不太了解Lua,但是您似乎可以节省五个字节:(n+1)/2to -~n/2; or n-i+1or-~n-i; i%2==0i%2<1; 而reverse() orreverse()or。另外,您的TIO版本和字节数都包含结尾的分号,这似乎不是必需的。不错的第一个答案。向我+1。欢迎来到PPCG!:)
凯文·克鲁伊森

2
实际上,您不需要任何分号。133字节,包括凯文的建议。
Jo King

@KevinCruijssen谢谢!请问-~n您的建议在做什么?绝对可以,但是我不明白为什么。
Azure高地

1
@AzureHeights当然。~是一元按位求反运算符。但是,对于代码高尔夫而言,重要的是与~i拥有相同的价值-i-1。因此,我们可以使用-~i代替i+1~-i代替i-1。这在两种情况下很有用,我都可以在您的答案中利用它们:摆脱括号,因为-~运算符优先于其他数学运算,因此(n+1)/2可以是-~n/2。另一个有用的部分是在某些情况下要消除空格,就像我对所做的那样or-~n-i
凯文·克鲁伊森

1
如果您想了解更多有关这方面的信息,请参见~以下x+1x-1两个相关提示:将一元代码用于将一元代码~用于a-b-1a+b+1。通读所有通用技巧以及特定于语言的技巧(在这种情况下为Lua打高尔夫球的技巧)可能会很有趣。:)
凯文·克鲁伊森




3

C(gcc)118108字节

这是不会赢的,但是它是一种不同的方法(或者至少,我认为是这样!)我没有进行字符串操作,而是利用了以下事实: 10X-1个 过度 [1 ..ñ]={999999},然后可以乘以得到适当的模式;printf()然后进行零填充以进行右对齐。

可悲的是,它int仅具有足够的范围(最多32位平台),最多可以处理9位数字,因此您需要转到long使用更大的模式。一种本机执行MP算术的语言可能可以将其用于某些用途。

多亏了ceilingcat的建议。

h,j,k;p(h){h=h?10*p(--h):1;}f(i){for(j=0,h=i++;k=++j>i/2?i-j:j,j<i;printf("%0*d\n",h,~-p(k)*p(j%2*(h-k))));}

在线尝试!


这适用于MP算术的概念证明:

C#(Mono C#编译器)187字节

(143个字节+ using System.Numerics;标头中的22个字节)

q=>{var r="";for(int j=0,h=q+1,k;j<q;r+=((BigInteger.Pow(10,k)-1)*BigInteger.Pow(10,j%2*(q-k))).ToString("D"+q)+"\n")k=++j>h/2?h-j:j;return r;}

在线尝试!


1
数字超出最大本机整数范围(使用C#和BigIntegers)的概念证明:在线尝试!
ErikF

3

Vim,99击键

尝试使用输入参数进行vim总是很有趣。这是非常不自然的,因此不会太短。可能还有其他好的方法。

假定输入本身是在缓冲区中。假定寄存器为空。假定编辑器足够高,可以包含结果而无需滚动(从技术上讲,这可以通过避免一些击键来避免)。

"nD@ni<cr><esc>MmaGddM
<c-v>'aI*<esc>qwgvjokoI*<esc>@wq@w<esc>
:set ve=all<cr>@nlh<c-v>@nkr#
:%s/ /#/g<cr>o<esc>
2Gqqdt#$p2j0@qq@q

说明

 | Buffer state (odd and even case):
 | 5                    6

"nD              read input into register n
@ni<cr><esc>     add n newlines
MmaGddM<c-v>'a   visual block select center row(s)
I*<esc>          prepend a column of *
qw               record macro w
  gvjoko         expand selection up and down
  I*<esc>
  @w             recurse
q
@w<esc>          run macro w and exit visual block select

 | Buffer state:
 | *                    *
 | **                   **
 | ***                  ***
 | **                   ***
 | *                    **
 |                      *

:set ve=all<cr>  move anywhere!
@nlh<c-v>@nkr#   add last column of #s

 | Buffer state:
 | *   #                *    #
 | **  #                **   #
 | *** #                ***  #
 | **  #                ***  #
 | *   #                **   #
 |                      *    #

:%s/ /#/g<cr>      replace spaces with #

 | Buffer state:
 | *####                *#####
 | **###                **####
 | ***##                ***###
 | **###                ***###
 | *####                **####
 |                      *#####

o<esc>2G           prep and jump to line 2
qqdt#$p2j0@qq@q    (effectively) flip every other onward

 | Buffer state:
 | *####                *#####
 | ###**                ####**
 | ***##                ***###
 | ###**                ###***
 | *####                **####
 |                      #####*

在base64中,使用实际字符(输入input和击键keys并使用来运行vim -u NONE -s keys input

Im5EQG5pDRtNbWFHZGRNFidhSSobcXdndmpva29JKhtAd3FAdxs6c2V0IHZlPWFsbA1AbmxoFkBua3IjOiVzLyAvIy9nDW8bMkdxcWR0IyRwMmowQHFxQHE=

2

[R,75字节

function(n)outer(1:n,1:n,function(x,y,a=x<y|x>n-y+1)+ifelse(x%%2,a,rev(a)))

在线尝试!

  • 灵感来自@Lynn答案
  • 函数获取n参数并返回0/1其中0对应于'*'1对应于的矩阵'#'

2

K(ngn / k),22字节

{"*#"i|:/'i>/:i&|i:!x}

在线尝试!

{ } 带参数的功能 x

!x清单(0;1;...;x-1)

i: 分配给 i

i&|i的最小值(&i及其反向(|

i>/:与右边列表中的每个元素的(>)比较大于()i/:) -返回布尔矩阵(名单列表)

i|:/'对于(')中的每个()j i,将对应的元素反向(|:-,我们必须:强制|一元)为j倍(n f/ xf n上应用次数x)。有效地,每隔一行反转一次。

"*#" 使用矩阵元素作为字符串中的索引 "*#"

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.