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 можно бесконечно укладывать с помощью +. Например, вывел a+a+a+a+aбы пять знаков плюс друг на друга.
Абсент

1
Разве это не дубликат codegolf.stackexchange.com/questions/18967/landscapes ?
Говард

@ Говард Да, вы правы, они удивительно похожи (единственное дополнение - это возможность отрезать башню и укладывать башни).
Мартин Эндер

@ Говард Ха Он не обнаруживается в похожих вопросах, которые появляются при вводе названия. Однако реализация пробелов немного отличается. Я отмечу свой пост как дубликат и посмотрю, что думают моды.
Абсент

Ответы:


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

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

РЕДАКТИРОВАТЬ: Только что понял, что это выглядит подозрительно похоже на решение 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 байта спасибо @ Веска

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.