ASCII соединенные шестиугольники

21

обзор

Учитывая количество шестиугольников, расположите их в соединенную форму в пределах изображения 50 на 50 ASCII. Форма, которую вы выбираете, может быть произвольной - что бы вы ни находили наиболее подходящей для игры в гольф - при условии, что она подключена. В нем могут быть отверстия при условии, что они больше одного шестиугольника (в противном случае количество шестиугольников будет неоднозначным).


раскладка

Все шестиугольники должны быть в следующей форме (действительны только этот размер и ориентация):

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

Два шестиугольника напрямую связаны, если они имеют общее ребро:

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

Два шестиугольника не связаны, если они только разделяют вершину:

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

Совместное использование половины ребра также не считается подключенным:

 __
/  \
\__/
 /  \
 \__/

Коллекция шестиугольников связана, если существует путь от любого шестиугольника до любого другого, использующего только непосредственно связанные шестиугольники.

Отверстия

Отверстие размером с шестиугольник в соединенном наборе шестиугольников считается шестиугольником, так что любое заданное произведение искусства ASCII имеет однозначное число шестиугольников.

Это не считается дырой, поскольку предполагаемая дыра представляет собой один шестиугольник:

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

Это делает подсчет как отверстие , так как он не соответствует одному шестиугольника:

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

Вход и выход

вход

Целое число от 1 до 255.

Выход

Художественная строка ASCII, представляющая количество входных шестиугольников, как описано выше.

  • Число строк (подстроки, разделенные символом новой строки) не более 50, плюс дополнительный необязательный завершающий символ новой строки.
  • Строки не обязательно должны быть одинаковой длины, но каждая из них должна иметь длину не более 50.
  • Строки нулевой длины могут существовать выше или ниже соединенной формы при условии, что общее количество строк не превышает 50.
  • Строки, содержащие только пробелы, могут существовать над или под соединенной формой, если общее количество строк не превышает 50.
  • Пробелы могут появиться слева от фигуры, если длина строк не превышает 50 (фигуру не нужно выравнивать по левому краю).
  • Пробелы могут появляться справа от фигуры, если длина строк не превышает 50.
  • Любые символы, которые не являются частью соединенной фигуры, должны быть либо пробелами, либо переводом строки.

При условии, что выходные данные верны, не требуется быть последовательным от одного прогона к следующему.

Примеры

Входные данные: 6

Действительные выходы:

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

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

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

Неверные выходы:

    __
 __/  \__
/  \__/  \
\__/  \__/
/  \__/  \
\__/  \__/
   \__/      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.

выигрыш

Самый короткий действительный ответ в байтах побеждает.


Leaderboard

(используя фрагмент списка лидеров Мартина )

Trichoplax
источник
Я боюсь, что все будут использовать первый пример шаблона вывода, так как он, вероятно, самый простой в реализации.
Fatalize
1
@ Фатализировать мои примеры работают только для ввода 6. Для ввода 255горизонтального ряда шестиугольников не вписывается в 50 на 50 ASCII-арт.
Трихоплакс
Вы все еще можете просто вернуться назад и заполнить строки ниже каждый раз, когда достигнете предела в 50 символов
Fatalize
1
@Fatalize Задача состоит в том, чтобы минимизировать количество байтов в коде. Я не против, если шаблоны просты, просто будет интересно посмотреть, что люди пробуют и что подходит для разных языков.
Трихоплакс
@Fatalize: Я не знаю, будет ли он коротким или нет, но более «интересный» ответ может сделать реальный поиск, чтобы увидеть, где можно разместить шестиугольники и, таким образом, получить более интересный результат.
Алекс Ван Лью

Ответы:

13

CJam, 64 57 55 байт

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

Проверьте это здесь.

Это сгенерирует следующий шаблон по столбцам :

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

объяснение

Это основано на превосходном наконечнике Денниса , использующем .e>для того , чтобы собрать художественную продукцию ASCII из нескольких частей. По его словам, для .e>каждого элемента берется максимум двух массивов (или строк), и поскольку пробелы имеют наименьший код символа, мы можем использовать это для наложения любых других символов в сетке строк. Кроме того, если два массива не имеют одинаковую длину, посторонние элементы более длинного массива просто копируются без изменений. Это означает, что разные шаблоны даже не должны быть одинакового размера. Чтобы применить это к двумерным массивам (потому что мы не хотим вставлять новые строки до самого конца), мы применяем .e>попарно к строкам, что дает ..e>.

Основная идея кода заключается в создании Nкопий одного шестиугольника, перемещенного в правильное положение. Мы «перемещаем» шестиугольник по вертикали, добавляя пустые строки, и по горизонтали, добавляя пробелы. Как только мы закончим, мы сложим все копии вместе, используя красивый :..e>(вероятно, самый длинный оператор, который я когда-либо использовал в программе CJam).

Вот код:

" __
/  \
\__/"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.
Мартин Эндер
источник
Чувак, я действительно должен выучить один из этих языков игры в гольф.
Алекс Ван Лью
@AlexVanLiew Вы должны! :) Но не потому, что это повышает ваши шансы на победу в коде, а потому, что CJam - прекрасный язык, на котором интересно программировать, и я не знаю другого языка, на котором вышеприведенное решение (которое я считаю довольно элегантным) имел бы смысл. ;)
Мартин Эндер
Я бы, наверное, выучил Pyth или оба; они оба в значительной степени одно и то же или один лучше остальных?
Алекс Ван Лью
@AlexVanLiew Я не знаю много Pyth, но я знаю, что они далеко не одно и то же. CJam - это основанный на стеке язык, в то время как Pyth возник как сокращение для Python (но теперь имеет свой собственный набор встроенных модулей). Pyth может немного есть верх , когда дело доходит до игры в гольф, но я лично очень нравится программировать в другой парадигме, так что я буду придерживаться CJam.
Мартин Эндер
Ага, понятно Я довольно хорошо знаю Python, поэтому я бы хотел изучить Pyth, но если у меня будет время, я тоже попробую CJam!
Алекс Ван Лью
7

Python 2, 219 207 символов

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

Принимает вход на стандартный ввод.

Практически просто создает сетку из 50х50 пространств и вставляет шестиугольники там, где это необходимо. После 16 - го шестиугольника, мне не нужен первый ряд h(шестиугольник в качестве 2D массива) , так что я использовать i>15для запуска диапазона на 1 вместо 0. c=i*3%48+1;r=(i*3+1)/48*2+i%2вычисляет с olumn и г вл мне нужно начать с. nявляется логическим значением, но используется как целое число для исправления границ (так h[0]как всего 3 символа, чтобы избежать перезаписи).

Я очень доволен этим, я срезал около 50 байтов с начальной версии, особенно когда я вспомнил a[x:y]=bсинтаксис.

Выход (n = 30):

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

Поскольку задние строки пробелов разрешены, я изменил создание так, gчтобы оно просто создавало 50 bytearrayс вместо 3+(x>1)+x/16*2точного количества строк, сокращая 12 байт.

Алекс Ван Лью
источник
6

Swift 2.0, 601 591 байт

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

Бежать: swift hexagons.swift 21

Выход:

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

Свифт substringToIndexи stringByReplacingOccurencesOfStringвзять столько персонажей ...

Дэвид Скрундз
источник
Я вообще не знаю Swift, но нет ли способа создать эту повторяющуюся строку с меньшим количеством кода?
Рето Коради
Единственный известный мне способ повторения строки - с помощью stringByPaddingToLength, однако в этом случае это будет на 11 символов длиннее, чем ввод полной строки.
Дэвид Скрундз
6
Я вижу, что Apple действительно нравится слишком многословная конкатенация строк. Не так плохо, как stringByAppendingStringв Objective-C, но все же ...
Fatalize
Вне гольф-кода это действительно хорошо, хотя и делает поиск метода намного проще.
JustSid
4

C 238 байт

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

Для подсчета символов учитываются только необходимые пробелы и символы новой строки.

Он просто создает матрицу символов, заполняет их в обратном порядке, а затем печатает все это.

Allbeert
источник
2

JavaScript (ES6), 265 байт

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

Тесселяция шестиугольников в ряд, слева направо, чередование вверх и вниз - как соты - до конца ряда.

Развернутый с описанием (работает в 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
источник
2

Рубин, 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}

создает массив из 50 строк по 50 пробелов, затем подставляет 4 символа в 3 строки, чтобы добавить шестиугольники:

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

Поскольку первая строка содержит пробелы, после того, как шестиугольник был нанесен, мы не можем построить еще один под ним, потому что пробелы будут перезаписывать предыдущие шестиугольники.

Поэтому шестиугольники добавляются в виде ромба 16x16 (искаженный прямоугольник) снизу вверх и наклоняются снизу слева направо вверх.

Затем строка " __ "будет перезаписана дополнительными \и, /где необходимо.

Неуправляемый в тестовой программе

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) 

Типичный выход (n = 250)

Здесь должно быть еще несколько строк пробелов в верхней части, чтобы получить в общей сложности 50, но я не знаю, есть ли способ заставить Stackexchange отформатировать, чтобы включить их.

                                              __  
                                           __/  \ 
                                        __/  \__/ 
                                     __/  \__/  \ 
                            __    __/  \__/  \__/ 
                         __/  \__/  \__/  \__/  \ 
                      __/  \__/  \__/  \__/  \__/ 
                   __/  \__/  \__/  \__/  \__/  \ 
                __/  \__/  \__/  \__/  \__/  \__/ 
             __/  \__/  \__/  \__/  \__/  \__/  \ 
          __/  \__/  \__/  \__/  \__/  \__/  \__/ 
       __/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
    __/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
 __/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \ 
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ 
\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/    
/  \__/  \__/  \__/  \__/  \__/  \__/  \__/       
\__/  \__/  \__/  \__/  \__/  \__/  \__/          
/  \__/  \__/  \__/  \__/  \__/  \__/             
\__/  \__/  \__/  \__/  \__/  \__/                
/  \__/  \__/  \__/  \__/  \__/                   
\__/  \__/  \__/  \__/  \__/                      
/  \__/  \__/  \__/  \__/                         
\__/  \__/  \__/  \__/                            
/  \__/  \__/  \__/                               
\__/  \__/  \__/                                  
/  \__/  \__/                                     
\__/  \__/                                        
/  \__/                                           
\__/                                              
Уровень реки St
источник