Архітектор ASCII


15

Ви не хочете платити гроші за дорогу архітектурну програму, тому ви вирішили зробити свою власну. Ви вирішили використовувати ASCII для проектування будинків. Ваша програма буде приймати одну строку, відформатовану певним чином, і програма виведе будівлю.

Вхідні дані

Введення складається з одного рядка символів. Можна вважати, що він містить лише букви a-j, цифри 1-9та символи -та +.

Опис виходу

Для кожної літери a-jпрограма виводить вертикальну лінію наступним чином. Ми будемо називати це стовпцем.

         .
        ..
       ...
      ****
     *****
    ******
   -------
  --------
 +++++++++
++++++++++
abcdefghij

Наприклад, вхід abcdefgfedefghgfedcвидасть:

             .
      *     ***
     ***   *****
    ***** *******
   ---------------
  -----------------
 ++++++++++++++++++
+++++++++++++++++++

Лист може бути префіксом з натуральним числом n, яке додасть nсимволи пробілу під стовпцем. Ми будемо називати це зміщенням. Наприклад, використовуючи Sдля позначення пробілу пробіл, вхід видасть 3b2b3b:

+ +
+++
S+S
SSS
SSS

Лист може також бути префіксом з негативним цілим числом -m, що видалить нижні m непробільні символи стовпця (не замінить їх на пробіл, видаліть їх повністю). Ми назвемо це шматочком. Наприклад, вхід -1j-2j-3j-4j-5j-6j-7j-8jвидасть:

.
..
...
*...
**...
***...
-***...
--***...
+--***..

Зсув та зріз можна застосувати до тієї ж лінії, але зміщення має бути першим. Іншими словами, лист може бути з префіксом n-m, де nрозмір зсуву і mрозмір зрізу. Наприклад, використовуючи Sдля позначення пробілу пробіл, вхід '2-4j' виводить:

.
.
.
*
*
*
S
S

Нарешті, +оператор, що використовується між двома стовпцями, вказує, що вони повинні укладатися один над одним у один і той же стовпець, а не в окремі стовпці. Наприклад, вихідний сигнал 2-4ja:

.
.
.
*
*
*
S
S+

Тоді як вхідні 2-4j+aвиходи:

+
.
.
.
*
*
*
S
S

Ось зразок введення:

abiehef+ehfhabc

І отриманий результат:

      *
      -
  .   -
  . . +. .
  * * +* *
  * * ****
  ********
  --------
  --------  -
 +++++++++ ++
+++++++++++++

Схоже на стару зруйновану башту замків.

Ось ще один зразок введення:

6b5b+a6b1-2d+3-4f1-2d+-2c+2-4f+1-2d+-2c2-2d+1-4g+1-2c+b+-2c+-4e2-7j+-4g+d+-2c+-4f2-7j+-5h+b+-2c+a+-3f2-7j+-7i+-4e+b+b+a+-4f2-7i+a+-7h+-4f+b+b+a+-4f2-7j+-7h+-4f+a+-7h+a+-7i+-4f2-7j+-7i+-6h+a+-7i+b+-4e3-7i+a+-7h+-4e+a+-7h+b+1-7h3-7j+1-4f+-7h+b+-4f+a3-7j+2-4f+a+-4f+b3-2d+-2d+3-4g+b3-2d+-2d+-2c

І отриманий результат:

      ****** +++
     ******+.*++
     ---++.+ ***
    -+-+++..++**
    -+--+++.+++*
    --++++.+..*
      +++++.+**
+++****.******  -
+++*****.**..  --
 +   ***....+..--
      ...+.....--
    --.........--
   ---......
   --

(Це повинен був бути Маріо, але не вийшло дуже добре ...)

Якщо специфікація все ще не зрозуміла, у мене є непрограмна реалізація, написана в Python 2.7. Ви можете запустити його та експериментувати, щоб зрозуміти, як працює специфікація. Ви також можете сміятися з моїх навичок програмування.

Це кодовий гольф, тому виграє найкоротший запис. Задавайте питання в коментарях, якщо незрозуміло.


Укладення більш ніж двох веж дійсне? Я бачу "2c + b + -2c" в одному з ваших прикладів, але я не можу зрозуміти, чи так ви їх склали.
AndoDaan

1
@AndoDaan Towers можна нескінченно складати за допомогою +. Наприклад a+a+a+a+a, виводиться п'ять знаків плюс один на одного.
абсент


@Howard Huh, ти маєш рацію, вони напрочуд схожі (єдині доповнення полягають у тому, щоб мати змогу зрубати вежу та поставити вежі).
Мартін Ендер

@Howard Huh. Це не відображалось у справі подібних питань, що з’являється під час введення заголовка. Однак реалізація простору пробілів трохи інша. Я позначу свій пост як дублікат і побачу, що думають модники.
абсент

Відповіді:


10

Рубі, 223 214 байт

g=$*[0].split(/(?<=[a-j])(?!\+)/).map{|r|r.scan(/(\d*)(-\d+)?([a-j])/).map{|a,b,c|' '*a.to_i+'++--***...'[-b.to_i..c.ord-97]}*''}
puts g.map{|s|s.ljust(g.map(&:size).max).chars.reverse}.transpose.map(&:join).join$/

Це було весело. :)

Хоча це повинно бути цілком очевидно, я виявив новий спосіб зробити ці завдання, коли рядки побудовані з стовпців: просто виконайте їх у рядках та перекладіть масив символів, перш ніж приєднатись до всього.

g=$*[0].split(/(?<=[a-j])(?!\+)/)               # Split into columns.
       .map{|r|                                 # For each column
            r.scan(/(\d*)(-\d+)?([a-j])/)       # Split into components.
             .map{|a,b,c|                       # For each component
                ' '*a.to_i+                     # Prepend spaces if any.
                '++--***...'[-b.to_i..c.ord-97] # Select the appropriate slice of the tower.
            }*''                                # Join all components together.
        }
puts g.map{|s|                                  # For each column
            s.ljust(g.map(&:size).max)          # Pad with spaces on the right such that. 
                                                # all columns are the same height.
            .chars.reverse                      # Turn into character array and reverse.
      }
      .transpose                                # Mirror in the main diagonal.
      .map(&:join)                              # Join lines.
      .join$/                                   # Join columns.

Був пробуючи різні стилі останнього рядка і вийшов з: puts (0..z=g.map(&:size).max-1).map{|i|g.map{|y|(v=y[z-i])?v:?\ }*''}. Але, мабуть, не так весело без транспорту.
Векторизований

@bitpwner Спасибі, я перегляну і перевірити це пізніше.
Мартін Ендер

2

Кобра - 473

Я не думаю, що Кобра ніколи не виграє одного з таких: /

use System.Text.RegularExpressions
class P
    def main
        r=Regex.matches(Console.readLine,r'(?<=^|[a-j])(([^a-j]*[a-j])+?)(?=[^+]|$)')
        z,l=0String[](r.count)
        for m in r.count,for n in'[r[m]]'.split('+'),l[m]+=' '.repeat(int.parse('0[Regex.match(n,r'(?<!-)\d+')]'))+'++--***...'[int.parse('0[Regex.match(n,r'(?<=-)\d+')]'):' abcdefghij'.indexOf(n[-1:])]
        for y in l,if y.length>z,z=y.length
        for x in-z+1:1
            for y in l,Console.write(if(-x<y.length,y[-x],' '))
            print

Все приємно та прокоментовано:

EDIT: Щойно зрозумів, що це виглядає підозріло схоже на рішення Ruby. Великі уми мислять однаково?

use System.Text.RegularExpressions
class P
    def main
        r=Regex.matches(Console.readLine,r'(?<=^|[a-j])(([^a-j]*[a-j])+?)(?=[^+]|$)')
        # Split into columns
        z,l=0,String[](r.count)
        # Assign the column-array
        for m in r.count
        # Loop through columns
            for n in'[r[m]]'.split('+')
            # Loop through individual letter instructions
            # - within columns
                l[m]+=
                # Add characters to the last column
                    ' '.repeat(int.parse('0[Regex.match(n,r'(?<!-)\d+')]'))+
                    # Any spaces, plus
                    '++--***...'[:' abcdefghij'.indexOf(n[-1:])]
                    # The default column string
                        [int.parse('0[Regex.match(n,r'(?<=-)\d+')]'):]
                        # Sliced to the right length
        for y in l,if y.length>z,z=y.length
        # Determine the maximum length of any column
        for x in-z+1:1
            for y in l
            # Loop through columns so that they rotate to the left
                Console.write(if(-x<y.length,y[-x],' '))
                # Write the character in the current position
            print
            # Insert newlines

2

Луа - 451

a=arg[1]j='++--***...'I=io.write M=string.match U=string.sub T=table.insert n=''y=0 t={}m=0 for i in a:gmatch('[%-%d]*[a-j]%+?')do b=M(i,'-(%d)')b=b or 0 s=M(U(i,1,1),'%d')s=s or 0 n=n..(' '):rep(s)..U(U(j,1,M(U(i,-2),'[a-j]'):byte()-96),1+b,-1)if U(i,-1,-1)~="+"then T(t,n)m=m<#n and #n or m n=""y=y+1 end end T(t,n)n=''for k,v in pairs(t)do n=#v<m and n..v..(' '):rep(m-#v)or n..v end for i=m,1,-1 do for k=0,m*y-1,m do I(U(n,i+k,i+k))end I'\n'end

Нічого особливого. Було весело перейменувати прикладне навантаження функцій на один раз. Пізніше я відредагую непільгований код.

Спробуйте це тут. Вибірка зразка:

SampleOutput


1

PowerShell , 214 212 209 206 200 байт

-3 байти дякую @Veskah

switch -r($args-split'(-?.)'){\+{$c=1}\d{sv('ps'[0-gt$_])$_}[a-j]{if(!$c){$t+=,''}$t[-1]+=' '*$p+-join'++--***...'[-$s..($_[0]-97)];$c=$p=$s=0}}($t|% Le*|sort)[-1]..1|%{-join($t|% *ht $_|% ch*($_-1))}

Спробуйте в Інтернеті!

Менш гольф-версія:

# make table with lines instead columns
switch -r($args-split'(-?.)'){
    \+ {$c=1}
    \d {set-variable ('ps'[0-gt$_]) $_}
    [a-j] {
        if(!$c){$t+=,''}
        $t[-1]+=' '*$p+-join'++--***...'[-$s..($_[0]-97)]
        $c=$p=$s=0
    }
}
# transpose
($t|% Length|sort)[-1]..1|%{
    -join($t|% padRight $_|% chars($_-1))
}

1
Regex з (-?.)повинен працювати теж
Veskah

приголомшливий! Спасибі.
маззи

0

Python 3, 268 байт

import re
q,t=[(p,' '*int(o or 0)+'++--***...'[-int(s or 0):ord(l)-96])for p,o,s,l in re.findall('(\+?)(\d?)(-\d)?(.)',input())],[]
while q:p,s=q.pop(0);t+=[t.pop()+s if p else s]
t=[*zip(*[[*c.ljust(max(map(len,t)))]for c in t])][::-1]
for l in t:print(*l,sep='')

Здебільшого неозорені:

# import the regex module
import re

# array to store initial input
q = []
# array to store translated output
t = []

# split string from stdin into column groups, like: ('plus or blank', 'offset or blank', 'slice or blank', 'letter')
# ex: 6b1-2d+a would become:
# [('','6','','b'), ('', '1', '-2', 'd'), ('+', '', '', 'a')]
i = re.findall('(\+?)(\d?)(-\d)?(.)',input())

# iterate through the groups returned by the regex
for p,o,s,l in i:
    # create offset string
    # int() cannot parse '', but empty strings are falsey,
    # so (o or 0) is equivalent to 'parse the string as an int, or return 0 if it is empty'
    offset = ' ' * int(o or 0)

    # get the starting point of the slice
    # since the regex returns the minus, it must be negated after converting the string to an int
    # as before, (s or 0) ensures that the slice is converted to an int properly
    start = -int(s or 0)
    # since 'a' is ordinal 97, this ensures that the end position will be 1-9
    end = ord(l) - 96
    # slice the largest possible column string with the calculated start and end positions
    a = '++--***...'[start:end]
    # add the space offset
    a = offset + a
    # add the plus sting and the column string to the array
    q.append( (p, a) )

# while q is not empty
while q:
    # remove the first item from the list and separate it into a plus variable and a column string
    p, s = q.pop(0)

    # if p is not blank, it is a '+'
    # if p is truthy, remove the last item added and add s to it
    # otherwise just return s
    # append the resulting item to the ongoing list
    t += [t.pop()+s if p else s]

temp = []
for c in t:
    # call len() on all items in t, then return the maximum length
    m = max(map(len, t))
    # left justify c by adding spaces to the right, up to m total characters
    c = c.ljust(m)
    # unpack c into a list
    # this is equivalent to list(c), but shorter
    c = [*c]
    # add the list of characters to the array
    temp.append(c)

t = temp

# t is currently a list of rows, and needs to be rotated so that it displays correctly
# input: 'abcdefghij'
# before:
#
# +
# ++
# ++-
# ++--
# ++--*
# ++--**
# ++--***
# ++--***.
# ++--***..
# ++--***...
#
# after:
#
#  ++++++++++
#   +++++++++
#    --------
#     -------
#      ******
#       *****
#        ****
#         ...
#          ..
#           .
# 
t = [*zip(*t)]
# t is currently upside down, reverse the list
t = t[::-1]

# for each line (currently a list of characters)
for l in t:
    # unpack the list into print as arguments, do not add a space between arguments
    print(*l,sep='')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.