Hexágonos conectados ASCII

21

Visión general

Dado un número de hexágonos, colóquelos en una forma conectada dentro de los límites de una imagen de arte ASCII de 50 por 50. La forma que elijas puede ser arbitraria, lo que sea que consideres más adecuado para jugar al golf, siempre que esté conectado. Puede tener agujeros siempre que sean más grandes que un hexágono (de lo contrario, el número de hexágonos será ambiguo).


Diseño

Todos los hexágonos deben estar en la siguiente forma (solo este tamaño y orientación son válidos):

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

Dos hexágonos están conectados directamente si comparten una ventaja:

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

Dos hexágonos no están conectados si solo comparten un vértice:

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

Compartir medio borde tampoco cuenta como conectado:

 __
/  \
\__/
 /  \
 \__/

Se conecta una colección de hexágonos si existe un camino desde cualquier hexágono a cualquier otro utilizando solo hexágonos conectados directamente .

Agujeros

Un agujero del tamaño de un hexágono en una colección conectada de hexágonos cuenta como un hexágono, por lo que cualquier pieza de arte ASCII tiene un recuento de hexágonos inequívoco.

Esto no cuenta como un agujero ya que el agujero potencial es un solo hexágono:

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

Esto hace recuento como un agujero, ya que no se corresponde con un único hexágono:

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

Entrada y salida

Entrada

Un entero del 1 al 255.

Salida

Una cadena de arte ASCII que representa el número de entrada de hexágonos conectados como se describió anteriormente.

  • El número de filas (subcadenas separadas por nueva línea) es como máximo 50, más una nueva línea final opcional adicional.
  • Las filas no necesitan tener la misma longitud, pero cada una debe tener una longitud máxima de 50.
  • Pueden existir filas de longitud cero por encima o por debajo de la forma conectada, siempre que el número total de filas no exceda de 50.
  • Las filas de solo espacio pueden existir por encima o por debajo de la forma conectada, siempre que el número total de filas no exceda de 50.
  • Los espacios pueden aparecer a la izquierda de la forma, siempre que las longitudes de las filas no excedan de 50 (la forma no necesita estar alineada a la izquierda).
  • Los espacios pueden aparecer a la derecha de la forma, siempre que las longitudes de las filas no excedan de 50.
  • Cualquier carácter que no forme parte de la forma conectada debe ser espacios o líneas nuevas.

Siempre que la salida sea correcta, no es necesario que sea coherente de una ejecución a la siguiente.

Ejemplos

Entrada: 6

Salidas válidas:

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

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

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

Salidas 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.

Victorioso

La respuesta válida más corta en bytes gana.


Tabla de clasificación

(usando el fragmento de la tabla de clasificación de Martin )

trichoplax
fuente
Me temo que todos usarán el primer patrón de salida de ejemplo, ya que probablemente sea el más fácil de implementar.
Fatalize
1
@Fatalize mis ejemplos solo funcionan para una entrada de 6. Para una entrada de 255una fila horizontal de hexágonos no cabe en un arte ASCII de 50 por 50.
trichoplax
Todavía puede simplemente retroceder y llenar las líneas a continuación cada vez que alcanza el límite de 50 caracteres
Fatalize
1
@Fatalize El desafío es minimizar el número de bytes en el código. No me importa si los patrones son simples, será interesante ver qué intentan las personas y qué se adapta a los diferentes idiomas.
trichoplax
@Fatalize: No sé si sería breve o no, pero una respuesta más "interesante" podría hacer una búsqueda real para ver dónde puede colocar hexágonos y así obtener una salida más interesante.
Alex Van Liew

Respuestas:

13

CJam, 64 57 55 bytes

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

Pruébalo aquí.

Esto generará el siguiente patrón, en columnas :

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

Explicación

Esto se basa en la excelente sugerencia de Dennis , que se usa .e>para ensamblar una salida de arte ASCII de varias piezas. Como él dice, .e>toma el máximo de dos matrices (o cadenas) en cuanto a elementos, y dado que los espacios tienen el código de caracteres más bajo, podemos usar esto para imponer cualquier otro carácter en una cuadrícula de cadenas. Además, si las dos matrices no tienen la misma longitud, los elementos extraños de la matriz más larga simplemente se copian sin cambios. Esto significa que los diferentes patrones ni siquiera necesitan ser del mismo tamaño. Para aplicar esto a las matrices bidimensionales (porque no queremos insertar las nuevas líneas hasta el final), aplicamos .e>pairwise a las líneas, lo que da ..e>.

La idea básica del código es generar Ncopias de un solo hexágono movido a la posición correcta. Nosotros "movemos" el hexágono verticalmente anteponiendo líneas vacías y horizontalmente anteponiendo espacios. Una vez que terminamos, doblamos todas las copias juntas, usando la hermosa :..e>(probablemente el operador más largo que he usado en un programa CJam).

Aquí está el 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
fuente
Hombre, realmente debería aprender uno de estos idiomas de golf.
Alex Van Liew
@AlexVanLiew ¡Deberías! :) Pero no porque mejore sus posibilidades de ganar código de golf, sino porque CJam es un lenguaje hermoso que es divertido de programar, y no conozco ningún otro idioma en el que la solución anterior (que creo que es bastante elegante) Habría tenido sentido. ;)
Martin Ender
Probablemente aprendería Pyth o ambos; ¿Ambos son más o menos lo mismo o uno mejor que el resto?
Alex Van Liew
@AlexVanLiew No sé mucho Pyth, pero sé que están lejos de ser lo mismo. CJam es un lenguaje basado en pila, mientras que Pyth se originó como una abreviatura de Python (pero ahora tiene su propio conjunto de elementos integrados). Pyth puede tener una ligera ventaja cuando se trata de jugar al golf, pero personalmente disfruto mucho de la programación en un paradigma diferente, por lo que me quedaré con CJam.
Martin Ender
Ajá ya veo. Conozco a Python bastante bien, por eso me gustaría aprender Pyth, pero si tengo tiempo, ¡tal vez le dé una oportunidad a CJam!
Alex Van Liew
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))

Toma entrada en stdin.

Prácticamente solo crea una cuadrícula de espacios de 50x50 y coloca los hexágonos donde corresponde. Después de la 16a hexagonal, que no necesito la primera fila de h(el hexágono como una matriz 2D) así que utilizo i>15para iniciar el rango en 1 en vez de 0. c=i*3%48+1;r=(i*3+1)/48*2+i%2calcula la c OLUMNA y r ow necesito para comenzar a. nes un booleano pero se usa como un entero para arreglar los límites (ya h[0]que solo tiene 3 caracteres para evitar sobrescribir cosas).

Estoy bastante contento con este, reduje unos 50 bytes desde la versión inicial, especialmente cuando recordé el a[x:y]=b sintaxis.

Salida (n = 30):

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

Dado que se permiten líneas finales de espacios en blanco, cambié la creación de gsolo para crear 50 bytearrays en lugar de 3+(x>1)+x/16*2, que es el número exacto de filas requeridas, recortando 12 bytes.

Alex Van Liew
fuente
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)}

Correr: swift hexagons.swift 21

Salida:

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

Swift substringToIndexy stringByReplacingOccurencesOfStringtoma tantos personajes ...

David Skrundz
fuente
No conozco a Swift en absoluto, pero ¿no hay una manera de construir esa cadena repetitiva con menos código?
Reto Koradi
La única forma en que sé repetir una cadena es con stringByPaddingToLength, sin embargo, en este caso sería 11 caracteres más largo que escribir la cadena completa.
David Skrundz
66
Veo que a Apple realmente le gusta la concatenación de cadenas excesivamente detallada. No es tan malo como stringByAppendingStringen Objective-C pero aún así ...
Fatalize
Fuera del código de golf, esto es realmente agradable, ya que hace que la búsqueda de un método sea mucho más fácil.
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);
}

Solo los espacios necesarios y las nuevas líneas consideradas para el recuento de caracteres.

Simplemente crea una matriz de caracteres, los llena en orden inverso y luego imprime todo.

Allbeert
fuente
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`
`)

Tesela hexágonos en una fila, de izquierda a derecha, alternando hacia arriba y hacia abajo, como un panal, hasta llegar al final de una fila.

Ungolfed con descripción (funciona en 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
fuente
2

Rubí, 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}

crea una matriz de 50 cadenas de 50 espacios, luego sustituye 4 caracteres en 3 líneas para agregar los hexágonos:

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

Como la primera línea contiene espacios, una vez que se ha trazado un hexágono, no podemos trazar otro debajo de él, porque los espacios sobrescribirán los hexágonos anteriores.

Por lo tanto, los hexágonos se agregan en forma de rombo de 16x16 (rectángulo distorsionado) de abajo hacia arriba, y se inclinan de abajo hacia la izquierda hacia arriba a la derecha.

La cadena " __ "se sobrescribirá con adicional \y /cuando sea necesario.

Sin golf en el programa de prueba

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) 

Salida típica (n = 250)

Debería haber algunas filas más de espacios en blanco en la parte superior aquí, para hacer un total de 50, pero no sé si hay una manera de hacer que Stackexchange los formatee para incluirlos.

                                              __  
                                           __/  \ 
                                        __/  \__/ 
                                     __/  \__/  \ 
                            __    __/  \__/  \__/ 
                         __/  \__/  \__/  \__/  \ 
                      __/  \__/  \__/  \__/  \__/ 
                   __/  \__/  \__/  \__/  \__/  \ 
                __/  \__/  \__/  \__/  \__/  \__/ 
             __/  \__/  \__/  \__/  \__/  \__/  \ 
          __/  \__/  \__/  \__/  \__/  \__/  \__/ 
       __/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
    __/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
 __/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/    
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/       
\__/  \__/  \__/  \__/  \__/  \__/  \__/          
/  \__/  \__/  \__/  \__/  \__/  \__/             
\__/  \__/  \__/  \__/  \__/  \__/                
/  \__/  \__/  \__/  \__/  \__/                   
\__/  \__/  \__/  \__/  \__/                      
/  \__/  \__/  \__/  \__/                         
\__/  \__/  \__/  \__/                            
/  \__/  \__/  \__/                               
\__/  \__/  \__/                                  
/  \__/  \__/                                     
\__/  \__/                                        
/  \__/                                           
\__/                                              
Level River St
fuente