Hexágonos conectados a ASCII

21

visão global

Dado um número de hexágonos, organize-os em uma forma conectada dentro dos limites de uma imagem artística de 50 por 50 ASCII. A forma escolhida pode ser arbitrária - o que você achar mais favorável ao golfe - desde que esteja conectada. Pode haver orifícios, desde que sejam maiores que um hexágono (caso contrário, o número de hexágonos será ambíguo).


Layout

Todos os hexágonos devem estar no seguinte formato (somente esse tamanho e orientação são válidos):

 __
/  \
\__/    Note there are 2 underscores per horizontal edge.

Dois hexágonos são conectados diretamente se compartilharem uma aresta:

 __               __
/  \__           /  \
\__/  \          \__/
   \__/    or    /  \
                 \__/

Dois hexágonos não estão conectados se eles compartilham apenas um vértice:

 __  __
/  \/  \
\__/\__/

Compartilhar meia borda também não conta como conectado:

 __
/  \
\__/
 /  \
 \__/

Uma coleção de hexágonos é conectada se existir um caminho de qualquer hexágono para outro usando apenas hexágonos conectados diretamente .

Buracos

Um furo do tamanho de um hexágono em uma coleção conectada de hexágonos conta como um hexágono, de modo que qualquer peça de arte ASCII tenha uma contagem de hexágonos inequívoca.

Isso não conta como um buraco, já que o buraco em potencial é um único hexágono:

    __
 __/  \__
/  \__/  \
\__/  \__/
/  \__/  \
\__/  \__/
   \__/      7 hexagons (not 6 with a hole)

Isso faz contagem como um buraco, uma vez que não corresponde a um único hexágono:

    __
 __/  \__
/  \__/  \__
\__/  \__/  \
/  \__   \__/
\__/  \__/  \
   \__/  \__/
      \__/      8 hexagons with a hole

Entrada e saída

Entrada

Um número inteiro de 1 a 255.

Saída

Uma sequência de arte ASCII representando o número de entrada de hexágonos conectados, conforme descrito acima.

  • O número de linhas (substrings separados por nova linha) é no máximo 50, mais uma nova linha à direita opcional.
  • As linhas não precisam ter o mesmo comprimento, mas cada uma deve ter no máximo 50.
  • Linhas de comprimento zero podem existir acima ou abaixo da forma conectada, desde que o número total de linhas não exceda 50.
  • Linhas com espaço apenas podem existir acima ou abaixo da forma conectada, desde que o número total de linhas não exceda 50.
  • Os espaços podem aparecer à esquerda da forma, desde que o comprimento da linha não exceda 50 (a forma não precisa ser alinhada à esquerda).
  • Os espaços podem aparecer à direita da forma, desde que o comprimento da linha não exceda 50.
  • Quaisquer caracteres que não façam parte da forma conectada devem ser espaços ou novas linhas.

Desde que a saída esteja correta, não é necessário que seja consistente de uma execução para a seguinte.

Exemplos

Entrada: 6

Saídas válidas:

 __    __    __
/  \__/  \__/  \__
\__/  \__/  \__/  \
   \__/  \__/  \__/

 __    __
/  \__/  \
\__/  \__/
/  \__/  \
\__/  \__/
   \__/

          __
 __      /  \
/  \__   \__/
\__/  \__/  \
   \__/  \__/
      \__/
      /  \
      \__/

Saídas inválidas:

    __
 __/  \__
/  \__/  \
\__/  \__/
/  \__/  \
\__/  \__/
   \__/      Invalid for 6 as the centre hole counts as a 7th hexagon.

 __    __    __      __
/  \__/  \__/  \    /  \
\__/  \__/  \__/    \__/
   \__/  \__/                Invalid as the 6 hexagons are not connected.

 __    __    __  __
/  \__/  \__/  \/  \
\__/  \__/  \__/\__/
   \__/  \__/           Invalid as vertex touching does not count as connected.

 __    __       __
/  \__/  \     /  \
\__/  \__/     \__/
/  \__/  \
\__/  \__/
   \__/       Invalid as the 6 connected hexagons are not the only visible characters.

Ganhando

A resposta mais curta válida em bytes vence.


Entre os melhores

(usando o snippet do cabeçalho de Martin )

Trichoplax
fonte
Receio que todos usem o primeiro exemplo de padrão de saída, pois provavelmente é o mais fácil de implementar.
Fatalize
1
@Fatalize meus exemplos funcionam apenas para uma entrada de 6. Para uma entrada de 255uma linha horizontal de hexágonos, não caberá na arte ASCII de 50 por 50.
Trichoplax
Você ainda podia simplesmente volta ao início e preencher as linhas abaixo cada vez que você atingir o limite de 50 caracteres
Fatalize
1
@Fatalize O desafio é minimizar o número de bytes no código. Não me importo se os padrões forem simples, será interessante ver o que as pessoas tentam e o que combina com diferentes idiomas.
Trichoplax
@Fatalize: Não sei se seria curto ou não, mas uma resposta mais "interessante" pode fazer uma pesquisa real para ver onde ele pode colocar hexágonos e, assim, obter uma saída mais interessante.
Alex Van Liew

Respostas:

13

CJam, 64 57 55 bytes

" __
/  \
\__/"N/{_SS/\+_47>S3*f{\+}_2>\@?}q~(*]:..e>N*

Teste aqui.

Isso irá gerar o seguinte padrão, em colunas :

 __    __    __    __    __    __
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/  \
\__/  \__/  \__/  \__/  \__/  \__/
/  \__/  \__/  \__/  \__/  \__/
\__/  \__/  \__/  \__/  \__/  \
/  \__/  \__/  \__/  \__/  \__/
\__/  \__/  \__/  \__/  \__/  \
/  \__/  \__/  \__/  \__/  \__/
\__/  \__/  \__/  \__/  \__/  \
/  \__/  \__/  \__/  \__/  \__/
\__/  \__/  \__/  \__/  \__/

Explicação

Isso se baseia na excelente dica de Dennis , usando .e>para montar uma saída de arte ASCII de várias peças. Como ele diz, .e>assume o máximo de duas matrizes (ou cadeias) em elementos e, como os espaços têm o código de caracteres mais baixo, podemos usá-lo para impor outros caracteres em uma grade de cadeias. Além disso, se as duas matrizes não tiverem o mesmo comprimento, os elementos estranhos da matriz mais longa serão simplesmente copiados inalterados. Isso significa que os diferentes padrões nem precisam ter o mesmo tamanho. Para aplicar isso a matrizes bidimensionais (porque não queremos inserir as novas linhas até o final), aplicamos em .e>pares às linhas, o que fornece ..e>.

A idéia básica do código é gerar Ncópias de um único hexágono movido para a posição correta. "Movemos" o hexágono verticalmente, acrescentando linhas vazias e horizontalmente, acrescentando espaços. Quando terminamos, dobramos todas as cópias juntas, usando o belo :..e>(provavelmente o operador mais longo que já usei em um programa CJam).

Aqui está o código:

" __
/  \
\__/"N/    e# Get a 2D character grid of the hexagon.
{          e# Read input N, repeat this block N-1 times.
  _        e#   Make a copy, so we leave the last hexagon on the stack.
  SS/\+    e#   Prepend two empty lines.
  _47>     e#   Make a copy and discard the first 47 lines.
  S3*f{\+} e#   Prepend 3 spaces to each line. This copy has been moved back to
           e#   the top and one column to the right.
  _2>      e#   Make a copy and discard another two lines.
  \@?      e#   If any lines were left after that, pick the copy in the next column,
           e#   otherwise, stay in the same column.
}q~(*      
]:..e>     e# Wrap all the hexagons in an array and fold them into a single grid.
N*         e# Join them with newline characters.
Martin Ender
fonte
Cara, eu realmente devo aprender uma dessas línguas de golfe.
Alex Van Liew #
@AlexVanLiew Você deveria! :) Mas não porque melhora suas chances de ganhar código de golfe, mas porque o CJam é uma linguagem bonita e divertida de programar, e eu não conheço nenhuma outra linguagem na qual a solução acima (que eu acho bastante elegante) teria feito sentido. ;)
Martin Ender
Eu provavelmente aprenderia Pyth ou ambos; ambos são praticamente a mesma coisa ou é melhor que o resto?
Alex Van Liew #
@AlexVanLiew Não conheço muito Pyth, mas sei que eles estão longe da mesma coisa. CJam é uma linguagem baseada em pilha, enquanto Pyth se originou como uma abreviação para Python (mas agora tem seu próprio conjunto de built-ins). Pyth pode ter um pouco de vantagem quando se trata de golfe, mas eu pessoalmente gosto muito de programar em um paradigma diferente, por isso vou ficar com o CJam.
Martin Ender
Aha eu vejo. Conheço Python muito bem, e é por isso que gostaria de aprender Pyth, mas se eu tiver tempo, talvez eu também experimente o CJam!
precisa
7

Python 2, 219 207 caracteres

b=bytearray(' ');h=['__ ','/  \\','\\__/'];k=range;x=input();g=[b*50for _ in k(50)]
for i in k(x):
 c=i*3%48+1;r=(i*3+1)/48*2+i%2
 for m in k(i>15,3):n=m==0;g[r+m][c+n:c+4-n]=h[m]
print"\n".join(map(str,g))

Aceita stdin.

Praticamente apenas cria uma grade de espaços 50x50 e coloca os hexágonos onde apropriado. Após o hexágono 16, que não é necessário a primeira fileira de h(o hexágono como uma matriz 2D), de modo que usar i>15para iniciar o intervalo no 1 em vez de 0. c=i*3%48+1;r=(i*3+1)/48*2+i%2calcula o c olumn e r OW preciso para começar a. né um booleano, mas é usado como um número inteiro para corrigir os limites (já que h[0]são apenas três caracteres para evitar a substituição de itens).

Estou muito feliz com este, raspei cerca de 50 bytes desde a versão inicial, especialmente quando me lembrei da a[x:y]=bsintaxe.

Saída (n = 30):

  __    __    __    __    __    __    __    __
 /  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__
 \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \
 /  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/
 \__/  \__/  \__/  \__/  \__/  \__/  \__/  \
    \__/  \__/  \__/  \__/  \__/  \__/  \__/
(plus 44 lines of spaces each 50 wide)

Como linhas finais de espaço em branco são permitidas, mudei a criação de gpara apenas criar 50 bytearrays em vez de 3+(x>1)+x/16*2, que é o número exato de linhas necessárias, cortando 12 bytes.

Alex Van Liew
fonte
6

Swift 2.0, 601 591 bytes

import Cocoa
var a=Int(Process.arguments[1])!,b="/  \\__".join([String](count:9,repeatedValue:""))+"/",c="\\__/  ".join([String](count:9,repeatedValue:""))+"\\",d=c.startIndex,e=c.endIndex,j=[c.stringByReplacingOccurencesOfString("\\",withString:" ").stringByReplacingOccurencesOfString("/",withString:" ").substringToIndex(advance(d,3*a,e)),b.substringToIndex(advance(d,3*a+a%2,advance(e,-1)))]
while a>0{j+=[c.substringToIndex(advance(d,3*a+1,e)),b.substringToIndex(advance(d,3*a+(a+1)%2,e)]
a<=16 ?j+=[" "+j.removeLast().substringFromIndex(advance(d,1))]:()
a-=16}
for l in j{print(l)}

Para correr: swift hexagons.swift 21

Saída:

 __    __    __    __    __    __    __    __    
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/
\__/  \__/  \__/
   \__/  \__/  

Swift's substringToIndexe stringByReplacingOccurencesOfStringocupam tantos personagens ...

David Skrundz
fonte
Não conheço o Swift, mas não existe uma maneira de construir essa sequência repetitiva com menos código?
Reto Koradi
A única maneira que conheço de repetir uma sequência é com stringByPaddingToLength, no entanto, nesse caso, seriam 11 caracteres a mais do que digitar a sequência completa.
David Skrundz
6
Vejo que a Apple realmente gosta de concatenação de string excessivamente detalhada. Não é tão ruim quanto stringByAppendingStringem Objective-C, mas ainda assim ...
Fatalize
Fora do código de golfe, isso é muito bom, pois facilita a pesquisa de um método.
JustSid
4

C, 238 bytes

#define h(A) c[m+A/4][n+A%4]
i,m,n;
f(a)
{
    char c[50][51];
    for(i=0;i<50;i++)for(m=0;m<51;m++)c[i][m]=m-50?32:0;
    for(;a;)
        m=a/12*2,n=a%12*3,a--%2?m=a/12*2+1,n=a%12*3+3:0,
        h(1)=h(2)=h(9)=h(10)=95,h(4)=h(11)=47,h(7)=h(8)=92;
    for(;i;)puts(c-i--+50);
}

Somente espaços e novas linhas necessários são considerados para a contagem de caracteres.

Ele simplesmente cria uma matriz de caracteres, preenche-os na ordem inversa e depois imprime a coisa toda.

Allbeert
fonte
2

JavaScript (ES6), 265 bytes

A=Array;f='forEach';U=x=1;y=0;a=A.from(A(51),_=>A.from(A(51),_=>' '));d=h=>(` __
/  \\
\\__/`.split`
`[f]((l,i)=>[...l][f]((c,j)=>{if('_/\\'.indexOf(a[x+i][y+j])<0)a[x+i][y+j]=c})),(x+=U*-2+1),(U=!U),(C-y<=3?((U=x+=2),y=0):y+=3),--h?d(h):a.map(d=>d.join``).join`
`)

Agrupe hexágonos em sequência, da esquerda para a direita, alternando para cima e para baixo - como um favo de mel - até o final de uma linha.

Sem jogar com a descrição (funciona no firefox):

'use strict';
const CAP = 51;
var a = Array.from(Array(51), () => Array.from(Array(51),() => ' '))

function draw (hexagons, x, y, a, up) {
  // x, y (row, col) represents the current position of the cursor
  /*
  
    Here's a map of the first three iterations:
    
            01234567
     0        __
     1     __/  \__
     2    /  \__/  \
     3    \__/  \__/

    For the first 17 iterations, the cursor will be at:
    
      # | x | y
      ----------
      1 | 1 | 0
      2 | 0 | 3
      3 | 1 | 6
      4 | 0 | 9
      5 | 1 | 12
      6 | 0 | 15
      7 | 1 | 18
      8 | 0 | 21
      9 | 1 | 24
     10 | 0 | 27
     11 | 1 | 30
     12 | 0 | 33
     13 | 1 | 36
     14 | 0 | 39
     15 | 1 | 42
     16 | 0 | 45
     17 | 3 | 0      <- moves back to the first row

  */
` __
/  \\
\\__/`
  // split the hexagon into three lines
  .split('\n').forEach((line, index) => {
    // and for each line
    ;[...line].forEach((char, j) => {
      // if the cursor position (x, y) translated
      // by (index, j) is not already part of a hexagon
      // then replace it with the current (index, j) piece
      // of the hexagon
      /*
         0123
       0  __
       1 /  \
       2 \__/
       
      */
      if ('_/\\'.indexOf(a[x + index][y + j]) < 0)
        a[x + index][y + j] = char
    })
  })
  
  // `up` represents the next hexagon
  // if true, the next hexagon will be drawn attached to
  // the top right edge of the current hexagon
  if (up) {
    x -= 1
  // otherwise, it'll be drawn attached to the bottom right edge
  } else {
    x += 1
  }

  // move three columns to the right
  y += 3
  // change directions
  up = !up

  // if within the right boundary of the 51x51 matrix,
  // move back to the left edge and down 2 rows
  // and draw the next hexagon as an `up` hexagon
  if (51 - y <= 3) {
    y = 0
    x += 2
    up = true
  }

  // if hexagons > 0, then recurse and draw the next hexagon
  // otherwise, return the array (join the columns in each row, then join each row
  // by a new line)
  return --hexagons ?
    draw(hexagons, x, y, a, up)
    : a.map(d => d.join('')).join('\n')
}

var n = parseInt(prompt('Number to draw:'))
var r = draw(n, 1, 0, a, true)
document.write('<pre>' + r.replace(/\n/g, '<br>') + '</pre>')

royhowie
fonte
2

Ruby, 120

->n{a=(1..50).map{' '*50}
n.times{|i|x=i%16*3
3.times{|j|a[47-i/16*2-x/3+j][x..x+3]=[' __ ','/  \\','\__/'][j]}}
puts a}

cria uma matriz de 50 seqüências de 50 espaços e substitui 4 caracteres em 3 linhas para adicionar os hexágonos:

" __ "
"/  \"
"\__/"

Como a primeira linha contém espaços, uma vez que um hexágono tenha sido plotado, não podemos plotar outro abaixo, porque os espaços substituiriam os hexágonos anteriores.

Portanto, os hexágonos são adicionados na forma de um losango de 16x16 (retângulo distorcido) de baixo para cima e inclinados da parte inferior esquerda para a parte superior direita.

A sequência " __ "será substituída por outras adicionais \e /onde for necessário.

Ungolfed in program program

g=->n{
  a=(1..50).map{' '*50}              #make an array of 50 strings of 50 spaces
  n.times{|i|                        #loop through all hexagons
    x=i%16*3                         #x coordinate of top left corner of hexagon, 16 per row
    3.times{|j|                      #loop through 3 lines to print hexagon.
      a[47-i/16*2-x/3+j][x..x+3]=    #47-i/16*2 : start at the bottom and work up. each row is 2 lines high and contains 16 hexagons. x/3 : slant upwards as the row moves right. 
       [' __ ','/  \\','\__/'][j]    #These are the symbols for each of the 3 lines required for a hexagon. [x..x+3] defines which characters have to be replaced in each string.
    }      
  }
  puts a                             #print to stdout
}

N=gets.to_i
g.call(N) 

Saída típica (n = 250)

Deve haver mais algumas linhas de espaço em branco na parte superior aqui, totalizando 50, mas não sei se existe uma maneira de obter o Stackexchange para formatar para incluí-los.

                                              __  
                                           __/  \ 
                                        __/  \__/ 
                                     __/  \__/  \ 
                            __    __/  \__/  \__/ 
                         __/  \__/  \__/  \__/  \ 
                      __/  \__/  \__/  \__/  \__/ 
                   __/  \__/  \__/  \__/  \__/  \ 
                __/  \__/  \__/  \__/  \__/  \__/ 
             __/  \__/  \__/  \__/  \__/  \__/  \ 
          __/  \__/  \__/  \__/  \__/  \__/  \__/ 
       __/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
    __/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
 __/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/    
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/       
\__/  \__/  \__/  \__/  \__/  \__/  \__/          
/  \__/  \__/  \__/  \__/  \__/  \__/             
\__/  \__/  \__/  \__/  \__/  \__/                
/  \__/  \__/  \__/  \__/  \__/                   
\__/  \__/  \__/  \__/  \__/                      
/  \__/  \__/  \__/  \__/                         
\__/  \__/  \__/  \__/                            
/  \__/  \__/  \__/                               
\__/  \__/  \__/                                  
/  \__/  \__/                                     
\__/  \__/                                        
/  \__/                                           
\__/                                              
Level River St
fonte