Кодирование длины дороги


21

В Соединенных Штатах два противоположных направления движения на дороге разделены пунктирной желтой линией, если проезд разрешен, и двумя сплошными желтыми линиями, если проезд не разрешен.

графика правил дорожного движения

(Только одна сторона может быть разбита, чтобы разрешить проход на этой стороне, и желтые линии могут означать другие вещи, такие как центральные или обратимые полосы, но нас не касается ни один из этих случаев.)

Напишите программу, которая в перспективе длины кодируются строки Pдля прохождения и Nдля не прохождения , и выводит версию ASCII соответствующей дороги. За исключением центральной линии, дорога всегда имеет один и тот же рисунок, что легко можно понять из приведенных ниже примеров.

Перед каждым Pи Nво входной строке будет положительное десятичное число . Это число определяет длину зоны прохождения или отсутствия зоны прохождения текущей части дороги.

Примеры

Ввод 12Nбудет производить 12 столбцов без проезжей части (все линии центра =):

____________


============

____________

На входе 12Pбудет получено 12 столбцов проходящей дороги ( - повторение центральной линии ):

____________


- - - - - - 

____________

Передача и отсутствие прохождения могут быть объединены, например 4N4P9N7P1N1P2N2P:

______________________________


====- - =========- - - -=-==- 

______________________________

Это 4 столбца без проходов, затем 4 без проходов , затем 9 без проходов и т. Д.

Обратите внимание, что зона прохождения всегда начинается с тире ( -) с левой стороны, а не с пробела ( ). Это обязательно.

Детали

  • На входе никогда не будет двух Nзон или двух Pзон подряд. например 4P5P, никогда не произойдет.
  • Вам не нужно поддерживать буквы без начального положительного числа. Обычная Pвсегда будет 1P, простая Nвсегда будет 1N.
  • Могут быть задние пробелы, если они не выходят за пределы последней колонны дороги. Там может быть один дополнительный завершающий перевод строки.
  • Вместо программы вы можете написать функцию, которая принимает закодированную строку длины строки и печатает или возвращает дорогу ASCII.
  • Принимает ввод любым стандартным способом (stdin, командная строка, функция arg).

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


Должна ли дорога быть асимметричной, или разрешено печатать 4 пробела на каждой стороне линии?
orlp

@orlp Если вы спрашиваете, может ли дорога быть шире, чем 5 рядов, то нет. Если вы спрашиваете, можно ли ставить пробелы в пустых строках над или под центральной линией, то да, если они сохраняются с помощью детализации, пункт 3.
Увлечения Кельвина,

Позвольте мне спросить на примере, является ли какой-либо из них действительным выводом? gist.github.com/orlp/0e0eae16d6e1fcda5e9b
orlp

@orlp Ни то, ни другое.
Увлечения Кэлвина

Ответы:


5

CJam, 38 байт

"_  - _":N3'=t:P;q~]2/e~z'
*"--"/"- "*

Как это устроено

Мы сначала назначить правильный столбец дороги к переменным Nи , Pа затем просто оценить строку ввода. Это оставляет пару длины и столбца в стеке. Мы группируем их, запускаем для них RLD, чтобы получить полные столбцы, транспонируем, чтобы присоединиться к ним, и, наконец, преобразуем непрерывные --в -.

:_  - _":N                    e# This is the no passing column. We assign it to N
          3'=t:P              e# Replace the '-' in N with '=" and assign it to P
                q~]2/         e# Read the input, evaluate it and then group it in pairs
                     e~       e# Run a run-length-decoder on the pairs
                       z'
*                             e# Transpose and join with new lines.
 "--"/                        e# Split on two continuous occurrence of -
      "- "*                   e# Join by an alternate "- "

Попробуйте онлайн здесь


6

JavaScript (ES6), 114

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

f=s=>(b=(s=s.replace(/(\d+)(.)/g,(x,n,b)=>(b<'P'?'=':'- ').repeat(n).slice(0,n))).replace(/./g,'_'))+`


${s}

`+b

5

RS , 252 символа

Хотя это может и не учитываться, потому что я добавил оператора сходимости в качестве грабежа Retina Мартина Бюттнера час назад ... Я не собираюсь здесь соревноваться. Это просто весело - создавать решения на основе регулярных выражений.

(\d+\D)/#\1
+(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)(?=\d*\D)/\1\1\1\1\1\1\1\1\1\1\2\3\4\5\6\7\8\9\10#
\d(?=\d*#N)/=
(^|(?<=\D))\d(?=\d*#P)/-
+(?<=-)\d\d(?=\d*#P)/ -
(?<=-)\d(?=\d*#P)/ 
#\D/
((?:(=|-| ))+)/A\1\n\n\n\1\n\nA\1\n
+(A_*)(.)/\1_
A/

Я получил строку 2 из ответа Retina Мартина «Языки программирования на протяжении многих лет» .

объяснение

(\d+\D)/#\1
+(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)(?=\d*\D)/\1\1\1\1\1\1\1\1\1\1\2\3\4\5\6\7\8\9\10#

Это делает много магии. См. Ответ я связал выше для получения дополнительной информации.

В основном, с вводом 4N4P9N7P1N1P2N2P, это будет результат:

4444#N4444#P999999999#N7777777#P1#N1#P22#N22#P

Следующий:

\d(?=\d*#N)/=

Это заменяет числа, предшествующие непроходному символу (N), на знаки равенства. Результат с предыдущего ввода:

====#N4444#P=========#N7777777#P=#N1#P==#N22#P

Это:

(^|(?<=\D))\d(?=\d*#P)/-

заменяет первое число, предшествующее проходящему символу (P), на первую черту. Результат:

====#N-444#P=========#N-777777#P=#N-#P==#N-2#P

Следующие две строки продолжают тот же шаблон:

+(?<=-)\d\d(?=\d*#P)/ -
(?<=-)\d(?=\d*#P)/ 

Первая строка заменяет остальную часть строки шаблоном черточки. Второй обрабатывает нечетное число; он заменяет последнюю черту, за которой следует единственное целое число (например, -5), тире-пробел ( -). Теперь вывод:

====#N- - #P=========#N- - - -#P=#N-#P==#N- #P

Теперь вещи начинают становиться на свои места. Следующая строка:

#\D/

просто удаляет #Nи #P.

((?:(=|-| ))+)/A\1\n\n\n\1\n\nA\1\n
+(A_*)(.)/\1_

установите подчеркивание сверху и снизу, чтобы получить:

A______________________________


====- - =========- - - -=-==- 

A______________________________

Наконец, мы удалим A:

A/

2

Haskell, 165 байт

k 'N'="="
k _="- "
d c=c>'/'&&c<':'
p[]=[]
p s=take(read$takeWhile d s)(cycle$k a)++p r where(a:r)=dropWhile d s
f s=unlines[q,"\n",p s,"",q]where q=map(\x->'_')$p s

Пример выполнения ( fвозвращает строку, поэтому для лучшего отображения выведите ее):

*Main> putStr $ f "4N4P9N7P1N1P2N2P"
______________________________


====- - =========- - - -=-==- 

______________________________

Как это работает: pвозвращает среднюю строку путем рекурсивного анализа входной строки и конкатенации заданного числа символов, найденных функцией поиска k. Основная функция fобъединяет список из пяти элементов с символами новой строки, состоящими из верхней строки (каждый символ средней строки заменен на _), новой строки, средней строки, пустой строки и нижней строки (аналогично верхней).


2

Python 3, 169 168 байт. (167 с Python 2)

p,s='',str.split
for _ in s('N '.join(s('P '.join(s(input(),'P')),'N'))):
 v=int(_[:-1]);p+=['='*v,('- '*v)[:v]][_[-1]=='P']
l=len(p)
u='_'*l
print(u+'\n'*3+p+'\n\n'+u)

Изрядно не одураченный

p=''
for i in'N '.join('P '.join(input().split('P')).split('N')).split():

  v=int(i[:-1])         # Get the number from the input section

  if i[-1]=='N':        # Check the letter (last char) from the input section
      p+=('='*v)        # Repeat `=` the number from input (v)
  else:
      p+=('- '*v)[:v]   #Repeat `- ` v times, then take first v chars (half)
l=len(p)                #Get the length of the final line markings
print('_'*l+'\n\n\n'+p+'\n\n'+'_'*l)

print('_'*l                          # Print _ repeated the length of p
           +'\n\n\n'                 # 3 new lines
                    +p+              # print out p (the markings)
                       '\n\n'        # 2 new lines
                             +'_'*l) # Print _ repeated the length of p

for i in
        'N '.join(
                  'P '.join(
                            input().split('P'))
                                               .split('N'))
                                                           .split():
                            # Split the input into items of list at P
                  # Join together with P and ' '
                                                # Split at N...
         # Join with N and ' '
                                                           # Split at space
# Loop through produced list

Попробуйте это онлайн здесь .


Вы забыли обновить количество байтов.
mbomb007

@ mbomb007 Это не изменило счет: / Я не могу получить его ниже 169 атм
Тим

Помещение p+=['='*v,('- '*v)[:v]][_[-1]=='P']в конец предыдущей строки предыдущей точкой с запятой экономит один байт.
mbomb007

Кроме того, использование Python 2 вместо этого экономит 1 байт на print.
mbomb007

@ mbomb007 добавил их :) У меня есть чувство, что Python 2 может быть даже короче ... Но я не уверен.
Тим

2

Python 2, 136 байт

Удивительно, но импорт reздесь действительно имеет смысл.

import re
s=""
for x,y in re.findall("(\d+)(.)",input()):s+=(("- ","==")[y=="N"]*int(x))[:int(x)]
t="_"*len(s);print t+"\n"*3+s+"\n"*2+t

2

PHP, 187 байт

preg_match_all('/(\d+)(\w)/',$argv[1],$m,2);
$o='';
foreach($m as $p)
    $o.=str_replace('--','- ',str_repeat($p[2]<'P'?'=':'-',$p[1]));
$a=preg_replace('/./','_',$o);
echo("$a\n\n\n$o\n\n$a\n");

Код может оставаться на одной строке; он отображается здесь на нескольких строках, чтобы быть более читабельным (пробелы и символы новой строки, использованные для форматирования, не учитывались).

Два байта можно сохранить, не печатая завершающий символ новой строки. Еще пять байтов можно сохранить, используя настоящие символы новой строки на echo():

echo("$a


$o

$a");

Шесть дополнительных байтов можно сохранить, пропустив инициализацию $o( $o='';), но это вызовет уведомление. Уведомление можно подавить, запустив скрипт с помощью командной строки:

$ php -d error_reporting=0 <script_name> 4N4P9N7P1N1P2N2P

Это приносит 174 байта.


2

Рубин, 137 135 байтов

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

require'scanf'
N='_  = _'
P='_  - _'
a=[]
scanf('%d%c'){|l,t|a+=[eval(t).chars]*l}
puts (a.shift.zip(*a).map(&:join)*?\n).gsub'--','- '

Ungolfed:

require 'scanf'

N = '_  = _'
P = '_  - _'
columns = [] # array of columns
# scan stdin for a number followed by a single char
scanf('%d%c') do |length, type|
  columns += [eval(type).chars] * length
done

# Convert to an array of rows, and join into a string
rows = columns.shift.zip(*columns).map(&:join)
str = rows * "\n" # join lines

# Replace '--' by '- ' and print
puts str.gsub(/--/, '- ')

Вы должны быть в состоянии улучшить это на 2 байта (и превзойти ответ Python 2), изменив последнюю строку на (a.shift.zip(*a).map(&:join)*?\n).gsub'--','- '.
blutorange

1

C 155 байт

main(l,v,k,n,x,s,c)char*s,**v,c;{for(l=6;l--;puts(s))for(s=v[1];*s;s+=k)for(x=sscanf(s,"%d%c%n",&n,&c,&k);n--;)putchar(l%5?l^2?32:c^78?++x&1?45:32:61:95);}

Более читабельно:

main(l,v,k,n,x,s,c)
    char*s,**v,c;
{
    for(l=6;l--;puts(s))
        for(s=v[1];*s;s+=k)
            for(x=sscanf(s,"%d%c%n",&n,&c,&k);n--;)
                putchar(l%5?l^2?32:c^78?++x&1?45:32:61:95);
}

Внешний цикл считает строки от 5 до 0.

Средний цикл перебирает части кодированной строки:

4N4P9N7P1N1P2N2P
4P9N7P1N1P2N2P
9N7P1N1P2N2P
7P1N1P2N2P
1N1P2N2P
1P2N2P
2N2P
2P
string is empty - exit

Внутренний цикл декодирует часть, например, 7Pи выполняет итерацию необходимое количество раз (например, 7).

Каждая итерация печатает один char. Значение charописывается кодом l%5?l^2?32:c^78?++x&1?45:32:61:95:

  • Если номер строки 5 или 0, выведите 95 ( _)
  • В противном случае, если номер строки не равен 2, выведите пробел
  • В противном случае, если символ «N», выведите 61 ( =)
  • В противном случае увеличьте xна 1 (оно было инициализировано до 2 с помощью sscanf)
  • Если нечетно, выведите 45 ( -), иначе выведите 32 (пробел)

0

Scala, 163 байта

(s:String)=>{val r=(("\\d+(P|N)"r) findAllIn(s) map(r=>{val l=r.init.toInt;if(r.last=='N')"="*l else ("- "*l).take(l)})).mkString;val k="_"*r.length;s"$k\n\n\n$r\n\n$k"}

Первая попытка, может быть, игра в гольф еще немного.


0

Рубин, 94 байта

Заимствует gsub'--','- 'идею от ответа 14mRh4X0r в . Я думаю, что ответ более интересен, хотя это короче.

f=->x{n=?_*x.gsub!(/(\d+)(.)/){($2==?P??-:?=)*$1.to_i}.size
"#{n}


#{x.gsub'--','- '}

#{n}"}

Тестирование:

f=->x{n=?_*x.gsub!(/(\d+)(.)/){($2==?P??-:?=)*$1.to_i}.size
"#{n}


#{x.gsub'--','- '}

#{n}"}

puts f['4N4P9N7P1N1P2N2P']

Производит:

______________________________


====- - =========- - - -=-==- 

______________________________

0

позвольте мне включить мою версию Matlab

MATLAB (267 б)

function d=p(V,a),j=numel(V)-1;if (a==0),d=0;return; end,d=(V(a)-48+10*p(V,a-1))*(V(a)<64);fprintf('%c%.*s%c%.*s',(a>=j)*10,(a==j|a==1)*eval(strcat(regexprep(V,'[NP]','+'),48)),ones(99)*'_',(a<3)*10,(V(a+1)>64)*d,repmat((V(a+1)==78)*'=='+(V(a+1)==80)*'- ',[1 99]));end

вход

Строка в формате ascii, заключенная в пробел (поскольку в matlab нет конца цепочки '\ 0')

пример V = '12N13P'


выход

образец представления дороги

_________________________


============- - - - - - -

_________________________

функция

функция должна вызываться из его tail-1 (пустой символ удаляется)

пример : p (V, цифра (V) -1)

моделирование

попробуйте это онлайн здесь


0

R, 132 байта

Не очень доволен этим, но это было немного забавно делать :) Пытался избавиться от множества gsubs, но мои усилия были напрасны. Я подозреваю, что есть намного лучший способ сделать это.

cat(rbind(nchar(a<-scan(,'',t=gsub('PN','P N',gsub('NP','N P',chartr('- =','PPN',scan(,'',sep='|')[4]))))),substring(a,1,1)),sep='')
  • scanполучает строки из STDIN и берет 4-й. Обратите внимание, что пустые строки требуют пробела (или чего-то) в них для сканирования, чтобы продолжить получать ввод.

    "==== - - ========= - - - - = - == -"

  • Он заменяет =s на Ns, на -и на Ps.

    "NNNNPPPPNNNNNNNNNPPPPPPPNPNNPP"

  • Затем он вставляет пробел между каждым NPиPN

    "НННН ПППП ННННННННН ПППППППП НП НН ПП"

  • Сканирование разбивает строку на пробелы

    "NNNN" "PPPP" "NNNNNNNNN" "PPPPPPP" "N" "P" "NN" "PP"

  • Длина строки затем связывается ( rbind) с первым символом каждой строки

    4 4 9 7 1 1 2 2
    "N" "P" "N" "P" "N" "P" "N" "P"

  • Затем массив выводится с использованием cat.

Тестовый забег

cat(rbind(nchar(a<-scan(,'',t=gsub('PN','P N',gsub('NP','N P',chartr('- =','PPN',scan(,'',sep='|')[4]))))),substring(a,1,1)),sep='')
1: ____________
2:  
3:  
4: ============
5:  
6: ____________
7: 
Read 6 items
Read 1 item
12N
> 
> cat(rbind(nchar(a<-scan(,'',t=gsub('PN','P N',gsub('NP','N P',chartr('- =','PPN',scan(,'',sep='|')[4]))))),substring(a,1,1)),sep='')
1: ____________
2:  
3:  
4: - - - - - - 
5:  
6: ____________
7: 
Read 6 items
Read 1 item
12P
> cat(rbind(nchar(a<-scan(,'',t=gsub('PN','P N',gsub('NP','N P',chartr('- =','PPN',scan(,'',sep='|')[4]))))),substring(a,1,1)),sep='')
1: ______________________________
2:  
3:  
4: ====- - =========- - - -=-==- 
5:  
6: ______________________________
7: 
Read 6 items
Read 8 items
4N4P9N7P1N1P2N2P
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.