Конвертировать экспоненты в искусство ASCII


28

задача

Ваша задача - преобразовать строки следующим образом:

abc^d+ef^g + hijk^l - M^NO^P (Ag^+)

Для таких строк:

   d   g       l    N P    +
abc +ef  + hijk  - M O  (Ag )

Что является приближением к abc d + ef g + hijk l - M N O P (Ag + )

Словами, поднимите символы непосредственно рядом с символами в верхней строке, один символ на один символ.

Спекуляции

  • Допускаются дополнительные конечные пробелы в выводе.
  • Никакие цепочки, такие как цепочки, m^n^oне будут введены в качестве входных данных.
  • За кареткой не последует сразу пробел или другая каретка.
  • Перед кареткой не будет сразу пробела.
  • Перед всеми каретками должен стоять хотя бы один символ, а за ним - хотя бы один.
  • Входная строка будет содержать только печатные символы ASCII (U + 0020 - U + 007E)
  • Вместо двух строк вы можете вывести массив из двух строк.

Для тех, кто говорит регулярное выражение: входная строка будет соответствовать этому регулярному выражению:

/^(?!.*(\^.\^|\^\^|\^ | \^))(?!\^)[ -~]*(?<!\^)$/

Leaderboard


2
@TimmyD «Входная строка будет содержать только печатаемые символы ASCII (U + 0020 - U + 007E)»
Leaky Nun

3
Зачем останавливаться на показателях? Я хочу что-то, что обрабатывает H_2O!
Нил

1
@Neil Тогда создай свой собственный вызов, и я могу закрыть его как его дубликат. :)
Дрянная Монахиня

1
Исходя из вашего примера, я бы сказал, что они являются суперпоказателями , а не обязательно показателями
Луис Мендо

4
Те, кто говорит на регулярных выражениях, родом из очень регулярной страны, где выражение жестко ограничено. Основной причиной смерти является катастрофический откат назад.
Дэвид Конрад

Ответы:


19

V , 15 14 байт

ÄÒ +òf^xxé kPj

Попробуйте онлайн!

Довольно простое решение. Идеальный вызов для V!

Объяснение:

Ä                "Duplicate this current line
 Ò               "Replace this line with spaces
   +             "Move to the beginning of the next line
    ò         ò  "Recursively (The second ò is implicit):
     f^          "  Find a caret
       xx        "  Delete two characters. The second will be saved into the main register
         é       "  Insert a space
           k     "  Move up
            P    "  Paste from the main register
             j   "  Move down

Удобно, основываясь на том, как работает рекурсия, это будет выполняться один раз для каждой каретки.


2
vim - идеальный язык для этой задачи. +1
Downgoat

18

Чеддер, 77 72 67 байт

l->l.chars.vfuse.replace("^\n"," ").lines.map(j->"%-2s"%j).turn(3)

Нет регулярных выражений!

Мне нравится этот ответ, так как он является прекрасной демонстрацией способностей Чеддера. Главным образом благодаря функции замены, добавленной Conor. PR для dev никогда не создавался, поэтому функция замены существует только в этой ветке (обновление: я сделал PR, и теперь он в последней бета-ветке, с которой вы можете установить npm install -g cheddar-lang)

Я нашел способ игры в гольф, но, к сожалению, недосмотр приводит к тому, что это происходит, когда длина предметов не одинакова:

["   denifednud   denifednug       denifednul    denifednuN denifednuP    denifednu+ ", "abcdenifednu +efdenifednu  + hijkdenifednu  - Mdenifednu Odenifednu  (Agdenifednu )"]

Я мог бы сэкономить много байтов, используя регулярные выражения, и на самом деле я только что сделал регулярные выражения для Cheddar ... единственная проблема в том, что нет никаких регулярных выражений: /

объяснение

l->                    // Function take input as `l`
   l.chars             // Get array of chars in input
   .vfuse              // Join with newlines
   .replace("^\n"," ") // Replace `^\n` with a space globally
   .lines              // Get the lines (see below for more details on what this returns)
   .map(j->            // Loop through each "line" `j` is arg
       "%-2s"          // C-like printf format.
                       // think of as: padRight(j, " ", 2)
                       // see below for more details
        % j            // Pass j as the string to insert
   ).turn(3)           // Turn the string 270 degrees (see below)
   .vfuse              // Vertically fuse to get result (this is not needed as we can output an array of the lines)

Чтобы лучше понять. Это то, что .linesвозвращается для1^2

["1", " 2"]

.turnс поворотом этим:

1
 2

в:

 2
1

Еще один пример, который сделает это более понятным:

1
 2
2
 2

будет выглядеть так:

 2 2
1 2

Почему формат?

То, что %-2sделает, довольно просто. %указывает, что мы запускаем «формат», или что переменная будет вставлена ​​в эту строку в этой точке. -означает правую строку, и 2это максимальная длина. По умолчанию он дополняется пробелами. sпросто указывает, что это строка. Чтобы увидеть, что он делает:

"%-2s" % "a"  == "a "
"%-2s" % " a" == " a"

2
: D Я всегда приветствую чеддер.
DJMcMayhem

@DrGreenEggsandIronMan: D спасибо
Downgoat

1
У чеддера есть turnметод для струн?
TuxCrafting

6
-1 Название этого языка всегда делает меня голодным.
перестал поворачиваться против часовой стрелки

@ TùxCräftîñg только для 2D-массивов, поэтому я использовал .lines для получения линий.
вниз

10

Perl, 21 + 1 = 22 байта

say'';s/\^(.)/♥[A\1↓/

Беги с -pфлагом. Замените необработанным ESCбайтом ( 0x1b) и вертикальной вкладкой ( 0x0b).

Вертикальная вкладка - идея Мартина Эндера. Это спасло два байта! Спасибо.


Разве вам не нужно перемещать курсор вниз по строке в начале, чтобы показатели не перекрывали последнее приглашение консоли?
Мартин Эндер

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

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

1
Какое прекрасное решение
Томас Уэллер

7

JavaScript (ES6), 56 55 байт

s=>[/.(\^(.))?/g,/\^.(())/g].map(r=>s.replace(r,' $2'))

Regexps на помощь, конечно. Первый заменяет все символы пробелами, если только он не находит каретку, в этом случае он удаляет каретку и сохраняет за ней символ. (Эти символы гарантированно существуют.) Второй является очевидным, чтобы заменить каждую каретку и ее следующий символ пробелом.

Редактирование: 1 байт сохранен благодаря @Lynn, который разработал способ повторного использования строки замены для второй замены, позволяющей отображать замену в массиве регулярных выражений.


2
Похоже, s=>[/.(\^(.))?/g,/\^.(())/g].map(r=>s.replace(r,' $2'))это байт короче.
Линн

@ Линн Это действительно хитрый трюк!
Нил

7

Python 3, 157 101 98 85 83 74 байта

Это решение отслеживает, был ли предыдущий символ ^, а затем решает, выводить ли в первую или вторую строку, основываясь на этом.

Выходы в виде массива ['firstline', 'secondline'].

a=['']*2
l=0
for c in input():x=c=='^';a[l]+=c*x;a[~l]+=' '*x;l=x
print(a)

Сохранено 13 15 байт благодаря @LeakyNun!

Сохранено 7 байтов благодаря @Joffan!


1
Хороший конечный автомат.
Утренняя монахиня

Было бы лучше иметь a=['',''] и объединять ' 'и cнепосредственно в a[l]и a[~l]?
Джоффан

6

Python 2, 73 байта

l=['']*2;p=1
for c in input():b=c!='^';l[p]+=c*b;l[~p]+=' '*b;p=b
print l

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


4

Pyth, 17 байт

CcsmX~Z1j;d;cQ\^2

             Q      input string
            c \^    split on '^'
   m                map for sections d:
    X      ;          insert a space at index:
     ~Z1                the old value of Z (initially 0), before setting Z to 1
                      into:
        j;d             the section joined on spaces
  s                 concatenate
 c              2   chop into groups of 2
C                   transpose

Возвращает массив из 2 строк. (Готовьтесь jприсоединиться к ним с новой строкой.)

Попробуйте онлайн .


1
Я не перестаю удивляться, как произносится твоя фамилия. : D
Линн

4

MATL , 18 байт

94=t1YSt~&vG*cw~Z)

Попробуйте онлайн!

94=    % Take input implicitly. Create logical array of the same size that contains
       % true for carets, false otherwise
t      % Push a copy of this array
1YS    % Circularly shift 1 unit to the right. This gives an array that contains true
       % for the elements right after a caret (superindices), and false for the rest 
t~     % Push a copy and negate
&v     % Concatenate vertically. This gives a 2D, 2-row array
G*     % Push the input again, multiply with broadcast. This gives a 2D array in
       % which the first row contains the superindices (characters after a caret)
       % and 0 for the rest; and the second row contains the non-superindices and
       % 0 for the superindices
c      % Convert to char
w      % Swap. Brings to top the array containing true for carets and false otherwise
~      % Negate
Z)     % Use as logical index to remove rows that contain carets. Display implicitly

4

Рубин, 47 + 1 ( -nфлаг) = 48 байт

puts$_.gsub(/\^(.)|./){$1||" "},gsub(/\^./," ")

Запустите это так: ruby -ne 'puts$_.gsub(/\^(.)|./){$1||" "},gsub(/\^./," ")'


Я думаю, что вы можете сохранить 1 байт, используя $_=$_.gsub(/\^(.)|./){$1||" "}+gsub(/\^./," ")и -pвместо -n.
Дом Гастингс

1
@DomHastings, независимо от того, работает он или нет, ваш код, похоже, не имеет новой строки, а добавление +$/означает, что он не будет сохранять байты. putsдобавляет новую строку для вас автоматически, когда ,между аргументами присутствует.
Value Ink

Ох ... Я тестировал с помощью, ruby -p ... <<< 'input'но я согласен, если он пропустил перевод строки, это не хорошо! На самом деле, я мог добавить новую строку в мои тесты раньше ... Это было на работе, поэтому я не могу проверить!
Дом Гастингс

@DomHastings Глядя на это еще раз, я предполагаю, что это потому, getsчто большую часть времени включает в себя завершающий символ новой строки, но если вы передадите конвейер в файл, который не содержит завершающий символ новой строки, он не появится, и результат будет неправильным , Протестируйте ваш код, ruby -p ... inputfileпоскольку Ruby перенаправляет в getsфайл, если это аргумент командной строки.
Value Ink

Понял, имеет смысл. Я думаю, что завершающий символ новой строки в файле также решит проблему. Я ни в коем случае не опытный Rubyist, поэтому я чувствую, что узнал немного больше об этом сегодня. Благодарность!
Дом Гастингс

3

Питон (2), 76 68 67 байт

-5 байт благодаря @LeakyNun

-3 байта благодаря @ KevinLau-notKenny

-1 байт благодаря @ValueInk

-0 байт благодаря @DrGreenEggsandIronMan

import re
lambda i,s=re.sub:[s("(?<!\^).\^?"," ",i),s("\^."," ",i)]

Эта анонимная лямбда-функция принимает входную строку в качестве единственного аргумента и возвращает две выходные строки, разделенные новой строкой. Чтобы назвать его, дайте ему имя, написав перед ним "f =".

Довольно простое регулярное выражение: первая часть заменяет следующее пробелом: любой символ и символ моркови или только символ, но только если перед ними нет знака. Вторая часть заменяет любую каретку в строке и символ после нее пробелом.


@LeakyNun: я по какой-то причине задавался вопросом, а также 1. выполняется ли импорт библиотек Копировал 2. в этот вопрос прямо сейчас, когда я увидел ваш комментарий. Спасибо тебе и Кевину!
КарлКастор

Вы можете снять один байт сfrom re import*
DJMcMayhem

@DrGreenEggsandIronMan Кажется, что используется точно такой же номер байта. (см. выше)
КарлКастор

Сохраните старый оператор импорта и сделайте lambda i,s=re.sub:[s("(?<!\^).\^?"," ",i),s("\^."," ",i)]для -1 байта
Value Ink


2

Сетчатка, 16 байт

S`^
\^(.)
♥[A$1↓

Порт моего Perl-ответа, на который указал Мартин Эндер. Заменить на необработанный ESCbyte ( 0x1b) и вертикальную табуляцию ( 0x0b).


2

shell + TeX + catdvi, 51 43 байта

tex '\empty$'$1'$\end'>n;catdvi *i|head -n2

Использует texнабор красивой математики, а затем использует catdviдля создания текстового представления. Команда head удаляет ненужную информацию (нумерацию страниц, завершающие символы новой строки), которая в противном случае присутствует.

Изменить: Зачем долго, правильно, вещь и перенаправление, /dev/nullкогда вы можете игнорировать побочные эффекты и писать в один файл письма?


пример

Входные данные: abc^d+ef^g + hijk^l - M^NO^P (Ag^+)

Вывод TeX (обрезается до уравнения): «Красивая» математика! Окончательный вывод:

   d   g     l  N P   +
abc +ef +hijk -M O (Ag )

Допущения: начинайте с пустого dir (или, в частности, dir без имени, оканчивающегося на «i»). Ввод - это единственный аргумент скрипта оболочки. Ввод не является пустой строкой.

Кто-то скажет мне, особенно если это нарушение правил catdvi.


2

Haskell, 74 56 55 байт

g('^':c:r)=(c,' '):g r
g(c:r)=(' ',c):g r
g x=x
unzip.g

Возвращает пару строк. Пример использования: unzip.g $ "abc^d+e:qf^g + hijk^l - M^NO^P: (Ag^+)"->(" d g l N P + ","abc +e:qf + hijk - M O : (Ag )")

g создает список пар, где первый элемент - это символ в верхней строке, а второй элемент - это символ в нижней строке. unzipпревращает его в пару списков.

Редактировать: @xnor предложил unzipсохранить 18 байтов. @Laikoni нашел еще один байт для сохранения. Благодарность!


Вы можете сделать j=unzip.g?
xnor

@xnor: как глупо с моей стороны не видеть этого самому! Большое спасибо!
Ними

Вы можете заменить g[]=[]на, g x=xчтобы сохранить один байт.
Лайкони

@Laikoni: хорошо заметили! Благодарность!
Ними

1

Perl, 35 байт

34 байтов код + 1 для -p

$_=s/\^(.)|./$1||$"/ger.s/\^./ /gr

использование

perl -pe '$_=s/\^(.)|./$1||$"/ger.s/\^./ /gr' <<< 'abc^d+ef^g + hijk^l - M^NO^P (Ag^+)'
   d   g       l    N P    + 
abc +ef  + hijk  - M O  (Ag )

Примечание: это точно так же, как ответ Value Ink , который я заметил позже. Удалит при необходимости, поскольку это не добавляет к решению Ruby.


1

Java 8 лямбда, 132 128 112 символов

i->{String[]r={"",""};for(char j=0,c;j<i.length();j++){c=i[j];r[0]+=c==94?i[++j]:32;r[1]+=c==94?32:c;}return r;}

Версия без гольфа выглядит так:

public class Q86647 {

    static String[] printExponents(char[] input) {
        String[] result = {"",""};
        for (char j = 0, c; j < input.length(); j++) {
            c = input[j];
            result[0] += c == 94 ? input[++j] : 32;
            result[1] += c == 94 ? 32 : c;
        }
        return result;
    }
}

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


Обновления

Заменены символы с их значениями ascii, чтобы сохранить 4 символа.

Спасибо @LeakyLun за указание использовать вместо него массив символов.

Также благодаря @KevinCruijssen для переключения intна , charчтобы сохранить еще несколько символов.


Вы можете попробовать ввести char[]и использовать, for(char c:i)чтобы увидеть, можно ли уменьшить количество байтов.
Утренняя монахиня

Вы можете увеличить его до 110 байт, используя: i->{String[]r={"",""};for(char j=0,c;j<i.length;j++){c=i[j];r[0]+=c==94?i[++j]:32;r[1]+=c==94?32:c;}return r;}с "abc^d+ef^g + hijk^l - M^NO^P (Ag^+)".toCharArray()вводом. ( Идея этих изменений. )
Кевин Круйссен

1

Кокос , 122 114 96 байт

Изменить: 8 26 байтов вниз с помощью Leaky Nun.

def e(s,l)=''==l and s or"^"==l[0]and l[1]+e(s+' ',l[2:])or' '+e(s+l[0],l[1:])
f=print..e$('\n')

Итак, как я узнал сегодня, у python есть троичный условный оператор, или фактически два из них: <true_expr> if <condition> else <false_expr>и <condition> and <true_expr> or <false_expr>последний из них идет с одним символом меньше.
Версия, соответствующая Python, может быть идеально .


Первая попытка:

def e(s,l):
 case l:
  match['^',c]+r:return c+e(s+' ',r)
  match[c]+r:return' '+e(s+c,r)
 else:return s
f=print..e$('\n')

Звонок с f("abc^d+ef^g + hijk^l - M^NO^P (Ag^+)")принтами

   d   g       l    N P    +
abc +ef  + hijk  - M O  (Ag )

Кто-нибудь пробовал еще играть в кокос? Он обогащает Python более функциональными концепциями программирования, такими как сопоставление с образцом и конкатенация функций (с ..), использованными выше. Поскольку это моя первая попытка кокосового ореха, любые советы будут оценены.

Это, безусловно, может быть сокращено, так как любой допустимый код Python также является допустимым, и более короткие ответы Python были опубликованы, однако я попытался найти чисто функциональное решение.


Я думаю, что вы можете использовать троичные операторы ( x and y or z) для замены case.
Дрянная Монахиня

Вы даже можете использовать s[0]=="^"вместоmatch['^',c]+r in l
Leaky Nun

@LeakyNun Когда я заменяю match['^',c]+rна s[0]=="^", тогда cи rбольше не связаны. Как это поможет?
Лайкони

Вы можете использовать, s[1]чтобы заменить cи s[2:]заменить r.
Дрянная Монахиня

тогда вы можете использовать троичный сейчас.
Дрянная Монахиня

0

Дьялог АПЛ, 34 байта

{(0 1=⊂b/¯1⌽b){⍺\⍺/⍵}¨⊂⍵/⍨b←⍵≠'∧'}

Возвращает двухэлементный вектор с двумя строками

Пробный прогон (вверху - форматирование двухэлементного вектора для потребления человеком):

      ↑{(0 1=⊂b/¯1⌽b){⍺\⍺/⍵}¨⊂⍵/⍨b←⍵≠'∧'}'abc∧d+ef∧g + hijk∧l - M∧NO∧P (Ag∧+)'
   d   g       l    N P    + 
abc +ef  + hijk  - M O  (Ag )

На ваш комментарий на мой вопрос о коде ничего не делает: да, тот код, который вы добавили, имеет значение.
Хайкам

0

PowerShell v2 +, 88 83 байта

-join([char[]]$args[0]|%{if($c){$_;$b+=' '}elseif($_-94){$b+=$_;' '}$c=$_-eq94});$b

Немного дольше, чем другие, но демонстрирует немного магии PowerShell и немного другую логику.

По сути, та же концепция, что и в Python, - мы перебираем вводимую букву за символом, помним, был ли предыдущая каретка ( $c), и помещаем текущий символ в соответствующее место. Однако логика и метод определения, куда выводить, обрабатываются немного по-другому и без кортежа или отдельных переменных - мы проверяем, был ли предыдущий символ кареткой, и если да, выводим символ в конвейер и объединяем пробел в $b, В противном случае мы проверяем, является ли текущий символ символом каретки, elseif($_-94)и, если это не так, мы объединяем текущий символ $bи выводим пробел в конвейер. Наконец, мы устанавливаем, является ли текущий персонаж кареткой для следующего раунда.

Мы собираем эти символы из конвейера вместе в паранах, инкапсулируем их в a, -joinчто превращает их в строку, и оставляем это вместе с$b конвейером. Вывод в конце неявный с новой строкой между ними.

Для сравнения вот прямой порт ответа Python @ xnor , 85 байтов :

$a=,''*2;[char[]]$args[($l=0)]|%{$a[!$l]+="$_"*($c=$_-ne94);$a[$l]+=' '*$c;$l=!$c};$a

0

Гема, 42 41 персонажа

\^?=?@set{s;$s }
?=\ @append{s;?}
\Z=\n$s

Gema обрабатывает ввод как поток, поэтому вы должны решить его за один проход: первая строка записывается сразу после обработки, вторая строка собирается в переменную $ s, а затем выводится в конце.

Образец прогона:

bash-4.3$ gema '\^?=?@set{s;$s };?=\ @append{s;?};\Z=\n$s' <<< 'abc^d+ef^g + hijk^l - M^NO^P (Ag^+)'
   d   g       l    N P    +  
abc +ef  + hijk  - M O  (Ag )

0

Корица, 21 байт

0000000: 5306 6533 bd92 d1db 8899 8381 a2f8 8f8c  S.e3............
0000010: 1230 249e a1                             .0$..

Неконкурирующий. Попробуйте онлайн.

объяснение

Я не большой любитель регулярных выражений, так что, вероятно, есть лучший способ сделать это.

Строка распаковывается в:

S(?<!\^)[^^]& &\^&`S\^.& 

(обратите внимание на завершающий пробел)

Первый Sэтап получает входные данные и использует отрицательный вид сзади, чтобы заменить все символы, кроме кареток, без предшествующей каретки пробелом, а затем удаляет все каретки. Затем он немедленно выводит измененную входную строку с новой строкой и удаляет этот Sэтап. Так как STDIN теперь исчерпан, и предыдущий этап не предоставил никакой информации, следующийS этап снова получает последнюю строку STDIN, а затем заменяет все символы вставки, за которыми следует любой символ, пробелом и выводит их.

В Perl псевдо-код:

$first_stage_sub_1 = ($input =~ s/(?<!\^)[^^]/ /gr);
$first_stage_sub_2 = ($first_stage_sub_1 =~ s/\^//gr);
print $first_stage_sub_2, "\n";

$second_stage_sub = ($input =~ s/\^./ /gr);
print $second_stage_sub, "\n";

0

J , 28 27 байт

0|:t#]{."0~_1-_1|.t=.'^'~:]

Попробуйте онлайн!

                  t=.'^'~:]    0 for ^, 1 for the rest, define t
              _1|.             Shift right, now zeroes are for superscripts         
     ]{."0~_1-                 Prepend that many spaces to each character
   t#                          Remove the rows with carets
0|:                            Transpose

Должен быть лучший способ ...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.