Сомнительный ^ H ^ H ^ H ^ H ^ H ^ Hspaces


47

На некоторых терминалах нажатие клавиши backspace генерирует управляющий код ^Hдля удаления предыдущего символа. Это породило странную идиому, где симулируются правки для комедийного эффекта :

Будьте добры к этому дураку ^ H ^ H ^ H ^ Hgentleman, он приезжает из корпоративного штаба.

Если задана строка с одним или несколькими ^Hсимволами, выведите результат возврата на каждый ^H. Для ввода будут использоваться только печатные символы (ASCII 32-126), и они ^будут отображаться только как ^H. Backspace никогда не произойдет на пустом тексте.

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

>> Horse^H^H^H^H^HCow
Cow

>> Be nice to this fool^H^H^H^Hgentleman, he's visiting from corporate HQ.
Be nice to this gentleman, he's visiting from corporate HQ.

>> 123^H45^H^H^H78^H
17

>> Digital Trauma^H^H^H^H^H^H^H^H^H^H^H^H^H^HMaria Tidal Tug^H^H^H^H^H^H^H^H^H^H^H^H^H^H^HDigital Trauma
Digital Trauma

Leaderboard

Вот список лидеров по языкам, любезно предоставленный Мартином Бюттнером .

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

# Language Name, N bytes

где Nразмер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:

# Ruby, <s>104</s> <s>101</s> 96 bytes


4
Является AAA^HB^H^Hдействительным?
Натан Меррилл

@NathanMerrill Да, и это приводит к A.
xnor

3
Я подозреваю, что сетчатка будет хорошо здесь.
Клавдиу

1
@Fatalize: «Backspace никогда не произойдет на пустом тексте».
Maltysen

16
@Maria Tidal Tug возвращается, чтобы преследовать меня
Digital Trauma

Ответы:


69

GNU sed, 11 байт

:;s/.^H//;t

Тестовый вывод:

$ echo "Horse^H^H^H^H^HCow
Be nice to this fool^H^H^H^Hgentleman, he's visiting from corporate HQ.
123^H45^H^H^H78^H
Digital Trauma^H^H^H^H^H^H^H^H^H^H^H^H^H^HMaria Tidal Tug^H^H^H^H^H^H^H^H^H^H^H^H^H^H^HDigital Trauma" | sed ':;s/.^H//;t'
Cow
Be nice to this gentleman, he's visiting from corporate HQ.
17
Digital Trauma
$ 

5
Смотри, кто появился! Это Мария Приливная буксир ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ H ^ HD Травма!
Алекс А.

@AlexA. Я скучаю по шутке?
user253751 14.07.15

@immibis: см . комментарий Digital Trauma по этому вопросу.
Алекс А.

sed -r ':;s/(^|.)\^H//;t'- это работает за счет дополнительных 6 байтов
aragaer

@aragaer Зачем это нужно? ОП говорит, что " Backspace никогда не произойдет на пустом тексте ". Я думаю, ^Hчто начало строки - это возврат на пустой текст.
Цифровая травма

19

Pyth, 11 байт

.U+PbZcz"^H

Демонстрация.

.U+PbZcz"^H
               Implicit: z = input()
      cz"^H    z.split("^H")
.U             reduce, with the first element of the list as the initial value.
   Pb          Remove the last character of what we have so far.
  +  Z         And add on the next segment.
               Print implicitly.

17

Гема, 6 байт

?#\^H=

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

bash-4.3$ gema -p '?#\^H=' <<< 'pizza is alright^H^H^H^H^H^Hwesome'
pizza is awesome

CW, потому что пример дурака против джентльмена занимает слишком много времени. (Убит после дня. Может быть, сбой в интерпретаторе? Все остальные примеры здесь обрабатываются за доли секунды.) На рекурсивный шаблон Gema, похоже, не влияет уровень рекурсии, но количество несоответствующего текста увеличивает время обработки экспоненциально ,


Есть ли ссылка на язык? Быстрый поиск на Github обнаружил немало
Sp3000

Конечно. gema.sourceforge.net (Кстати, проект Gema был зарегистрирован 2003-10-27, а GitHub был запущен 2008-04-10. Это может быть причиной, по которой его там нет.)
manatwork

Я считаю, что глубина рекурсии равна длине несоответствующей строки, потому что она будет повторяться снова и снова до \^Hсовпадений, сопоставляя по одному символу за раз ?.
Исаак

15

C, 52 байта

j;f(char*s){for(j=0;*s=s[j];s[j]==94?s--,j+=3:s++);}

Мы определяем функцию, fкоторая принимает указатель на строку в качестве ввода. После вызова функции этот указатель будет содержать измененную строку.

Простой тест:

int main(int argc, char** argv) {
    char buf[300] = "Digital Trauma^H^H^H^H^H^H^H^H^H^H^H^H^H^HMaria Tidal Tug^H^H^H^H^H^H^H^H^H^H^H^H^H^H^HDigital Trauma";
    f(buf);
    printf(buf);
    return 0;
}

Вышеуказанные отпечатки:

Digital Trauma

1
Это было действительно умно. Я заметил пару вещей: глобальные переменные уже инициализированы нулем, поэтому нет необходимости инициализировать jв вашем forцикле (конечно, тогда это одноразовое использование, но я ничего не вижу в правилах :)). Вы также можете объединить назначение с декрементом: j;f(char*s){for(;s[j]==94?*s--=s[j],j+=3:s++);}(47 байт)
Коул Камерон


@undergroundmonorail черт, я просто дважды проверил, не пропустил ли я это. Я все еще новичок в коде гольф, но я буду помнить это в будущем :). Спасибо за информацию!
Коул Кэмерон

1
@ColeCameron Это имеет непоследовательную модификацию и доступ (UB) и вызывает немедленную EXC_BAD_ACCESS на моем компиляторе / машине, к сожалению.
BrainSteel

1
@Quentin Я пробовал это, но из-за запятой s--, j+=3и приоритета оператора, это не работает правильно.
BrainSteel

14

Haskell, 47 байтов

h(a,_:_:b)=f$init a++b;h(x,_)=x
f=h.span(/='^')

Определяет функцию f :: String -> String. Как это устроено:

    f "ab^Hc^Hd"
=== h ("ab", "^Hc^Hd")   (find ^H)
=== f ("a" ++ "c^Hd")    (backspace)
=== f "ac^Hd"            (join)
=== h ("ac", "^Hd")      (find ^H)
=== f ("a", "d")         (backspace)
=== f "ad"               (join)
=== h ("ad", "")         (find ^H)
=== "ad"                 (no ^H: base case)

1
Я думаю, что вы можете сохранить байт, поменяв местами два случая hи выполнив h(x,_)=xдля случая пустой строки.
Згарб

12

CJam, 14 13 байтов

q"^H"/{W\ts}*

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

q                   e# Read the entire input
 "^H"/              e# Split it on occurrences of string "^H"
      {    }*       e# Reduce on the split array
       W\t          e# This is the tricky part. We know that if there are two parts that we
                    e# are reducing on, they must be separated by "^H". Which in turn means
                    e# that from the first part, last characters needs to be deleted
                    e# So we simply put the second part in place of the last character of the
                    e# first part.
          s         e# Doing the above makes it a mixed array of character and string.
                    e# So we convert it to a single string, ready to be served as first part
                    e# in next reduce iteration

ОБНОВЛЕНИЕ: 1 байт сохранен благодаря jimmy23013

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


2
1 байт короче: W\ts.
jimmy23013

11

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

Сетчатка

+`.\^H(.*)
$1

Две строки должны идти в свои собственные файлы, но вы можете запустить код как один файл с -sфлагом.

На каждом шаге мы удаляем первое совпадение .\^Hв строке. Мы повторяем это (с +модификатором), пока не произойдет удаление.


Просто любопытство: почему захват (.*), как кажется, просто откладывается без изменений?
manatwork

1
@manatwork Таким образом, мы только захватить первое .\^Hза один шаг. В противном случае abc^H^H^Hрезультат будет ab^после первого шага.
Рандомра

4
Извините за то, что еще не реализован лимит на замену (что, вероятно, позволило бы что-то подобное +1`.\^H). ;)
Мартин Эндер

10

JavaScript ( ES6 ), 39 байт

f=s=>(t=s.replace(/.\^H/,''))!=s?f(t):t

// TEST

Out=x=>O.innerHTML+=x+'\n'

Test=_=>(Out(I.value + "\n-> " + f(I.value)),I.value='')

;["Horse^H^H^H^H^HCow"
,"Be nice to this fool^H^H^H^Hgentleman, he's visiting from corporate HQ."
,"123^H45^H^H^H78^H"
,"Digital Trauma^H^H^H^H^H^H^H^H^H^H^H^H^H^HMaria Tidal Tug^H^H^H^H^H^H^H^H^H^H^H^H^H^H^HDigital Trauma"]
.forEach(t => Out(t + "\n-> " + f(t)))
#I { width:400px }
<pre id=O></pre>
<input id=I><button onclick='Test()'>-></button>


10

Perl, 20 16 15 байт

(14 символов кода + 1 символ опции командной строки.)

s/.\^H//&&redo

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

bash-4.3$ perl -pe 's/.\^H//&&redo' <<< "Be nice to this fool^H^H^H^Hgentleman, he's visiting from corporate HQ."
Be nice to this gentleman, he's visiting from corporate HQ.

1
Сохранить 4 персонажа:1while s/.\^H//
Кевин Рид

Вау! Это здорово @KevinReid. Спасибо.
manatwork

1
Еще один:s/.\^H//&&redo
Денис

Спасибо, @ Денис. redoкак-то не пробился в мои навыки. Придется изменить это.
Манатворк

2
Обратите внимание, что версия @ Dennis будет работать (как задумано), только если это единственный оператор внутри цикла или { }блока. (Причина, по которой он работает, perl -pзаключается в том, что -pкоммутатор автоматически оборачивает ваш код в whileцикл.) Версия Кевина работает в любых условиях.
Илмари Каронен,

9

Юлия, 58 42 41 байт

Сэкономлено 16 байтов благодаря manatwork и 1 благодаря Glen O!

f(s)='^'s?f(replace(s,r".\^H","",1)):s

Это создает рекурсивную функцию, которая принимает строку и возвращает строку.

Это заменяет одно вхождение за ^Hраз пустой строкой, в то время как вход содержит ^.

Примеры:

julia> f("123^H45^H^H^H78^H")
"17"

julia> f("pizza is alright^H^H^H^H^H^Hwesome")
"pizza is awesome"

Это первый раз, когда я видел Джулию в дикой природе. Приятно!
Ogaday

8

REGXY, 10 байт

Использует REGXY , язык подстановки регулярных выражений. Заменяет любой символ, сопровождаемый ^ H, ничем. Затем выполняется вторая строка, которая является просто указателем на предыдущую строку, повторяя подстановку, пока она не будет соответствовать.

/.\^H//
//

Это компилируется и выполняется правильно с примером интерпретатора в ссылке выше, но решение, возможно, немного дерзкое, поскольку оно основано на допущении в неопределенности языковой спецификации. Спецификация утверждает, что первый токен в каждой строке (перед /) действует как метка, но предполагается, что нулевой указатель метки будет указывать на первую команду в файле с нулевой меткой (или другими словами, это 'null' является допустимой меткой). Менее нахальное решение было бы:

a/.\^H//
b//a

Что составляет 13 байтов.


7

Python 3, 53 байта

o=""
for x in input().split("^H"):o=o[:-1]+x
print(o)

Но лично мне больше нравится эта словесная версия:

H=input().split("^H")
print(eval("("*~-len(H)+")[:-1]+".join(map(repr,H))))

Интересно то, что

'B''a''c''k''h''a''n''d''e''d'[:-1][:-1][:-1][:-1][:-1][:-1]

на самом деле работает и дает 'Back', поэтому я попытался отобразить ^H -> [:-1]и любой другой символ c -> 'c'тогда eval, но, к сожалению, у вас не может быть никаких строк впоследствии без +, так что это не получается:

'B''a''c''k''h''a''n''d''e''d'[:-1][:-1][:-1][:-1][:-1][:-1]'s''p''a''c''e''s'

Эй, это довольно опрятно.
Алекс Ван Лью

+=работает в цикле
CalculatorFeline

@CatsAreFluffy Это o=o[:-1]+x, неo=o+x
Sp3000

Упс, пропустил это. Что-то вроде o[:-2]=xработы?
CalculatorFeline

@CatsAreFluffy Вы не можете назначить наstr
Sp3000

7

Haskell, 52 47 байт

import Data.Lists
foldl1((++).init).splitOn"^H"

Пример использования:

> map (foldl1((++).init).splitOn"^H") ["Horse^H^H^H^H^HCow", "123^H45^H^H^H78^H", "Digital Trauma^H^H^H^H^H^H^H^H^H^H^H^H^H^HMaria Tidal Tug^H^H^H^H^H^H^H^H^H^H^H^H^H^H^HDigital Trauma"]
["Cow","17","Digital Trauma"]

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

                  splitOn"^H"     -- split on substring "^H", e.g "Horse^H^H^H^H^HCow" -> ["Horse","","","","","Cow"]
                 .                -- then
foldl1(         )                 -- fold from left by
            init                  --   first dropping the last char from the left argument
       (++).                      --   second concatenating left and right argument

6

Рубин, 27 24 20 байт

(19 символов кода + 1 символ командной строки.)

$_=$`+$'while/.\^H/

Благодаря:

  • Ventero за предложение использовать глобальные переменные (-4 символа)

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

bash-4.3$ ruby -pe '$_=$`+$'"'"'while/.\^H/' <<< "Be nice to this fool^H^H^H^Hgentleman, he's visiting from corporate HQ."
Be nice to this gentleman, he's visiting from corporate HQ.

+1 Я думал, что сделаю ответ Ruby, пока не увижу это - я уверен, что он настолько мал, насколько это возможно. Отличное использование []!
Даньеро

В начале была другая версия: loop{$_[/.\^H/]=""}rescue""эта более приятная, поскольку она демонстрирует крутость обработки исключений в Ruby.
manatwork

Ха-ха, это здорово :)
Даниеро

1
Лучше поздно, чем никогда: $_=$`+$'while~/.\^H/на 20 (вы можете даже сбросить тильду, если вас не волнует regexp literal in conditionпредупреждение).
Вентеро

1
@manatwork: Технически он появляется во всех версиях ruby> = 1.9 (регулярные выражения и строковые литералы в условиях устарели после 1.8), я думаю, что вы rubyпросто по умолчанию используете 1.8, тогда как irbиспользует ruby ​​2.1.5.
Вентеро

4

Python 2, 50

Немного странно, что там есть секунда lambda, но пока, похоже, лучший Python.

lambda s:reduce(lambda a,b:a[:-1]+b,s.split('^H'))

3

Pyth - 19 байт

Реду работает действительно, очень хорошо с этим, но он делает только один символ за раз, поэтому мне пришлось потратить почти столько же символов, сколько и действующий алгоритм, чтобы заменить ^Hна разрыв строки. Ищите лучший способ сделать это.

u?+GHnHbPGjbcz"^H"k

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


3

TeaScript , 7 байтов [не конкурирует]

Не конкурировать, так как TeaScript был создан после того, как этот вызов был опубликован. Это здесь в качестве ссылки.

xW/.\^H

При этом используется новый TeaScript 3 и рекурсивные замены для удаления символов


1
По какой-то причине это считается 8859 байтов в таблице лидеров из-за ссылки ISO 8859 ...
ev3commander

regerence? xD
кошка

2

К5, 64 байта

K на самом деле не предназначен для такой работы ...

{[s]$[2>#s;s;`=t:*&{"^H"~2#x_s}'1+!-2+#s;s;,/2#2!|(0,t,3+t)_s]}/

2

golflua, 36 байт

\f(s)@o!=s o=s;s=s:g(".^H","",1)$~s$

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

Lua 5.2.2  Copyright (C) 1994-2013 Lua.org, PUC-Rio
> \f(s)@o!=s o=s;s=s:g(".^H","",1)$~s$
> w(f("Be nice to this fool^H^H^H^Hgentleman, he's visiting from corporate HQ."))
Be nice to this gentleman, he's visiting from corporate HQ.

2

Javascript, 62 байта

Не самый короткий, но отлично работает.

t=prompt();while(t.match(R=/.\^H/))t=t.replace(R,'');alert(t);

Это, вероятно, может быть сокращено много!


1
Не самый короткий и не работает ни один (попробуйте любой из тестовых случаев). Регулярное выражение не должно быть глобальным (удалить / г)
edc65

@ edc65 Спасибо за совет. Я попробовал некоторые вещи, и они работали. Вот почему я написал так
Исмаэль Мигель

2

R, 54 52 байта

f=function(s)ifelse(s==(r=sub(".\\^H","",s)),r,f(r))

Та же основная идея, что и у моего Джулии . Это создает рекурсивную функцию, которая принимает строку и возвращает строку. Если вход равен самому себе с единственным вхождением ^Hудаленного, верните его, в противном случае вызовите функцию снова.

Вы можете попробовать это онлайн !


2

ECMAScript 6, 57 байт

s=>{while(~s.indexOf`^H`)s=s.replace(/.\^H/,'');return s}

Это, вероятно, игра в гольф, просто должен придумать способ, вероятно, нет


2
Как насчет s=>{while(s!=(s=s.replace(/.\^H/,""));return s}?
ЛРН

Или, если whileи returnслишком долго, это может быть рекурсивной:var f=s=>s==(s=s.replace(/.\^H/))?s:f(s)
ЛРН

@lm вы должны добавить второй параметр "" для замены. Тогда у вас есть мой ответ :)
edc65

Правда. И аргумент пустой строки должен быть там, я, должно быть, скопировал неправильную версию :(
lrn

~s.indexOf`^H`может стать/\^H/.test(s)
Не то, что Чарльз

2

Ява, 78 77 байт

String f(String a){while(!a.equals(a=a.replaceFirst(".\\^H","")));return a;}

1
Вы можете удалить пробел после запятой, чтобы сохранить один символ.
ProgramFOX

2

(Visual) FoxPro любая версия 80 байт

PARA t
DO WHILE AT('^H',t)>0
t = STRT(t,SUBS(t,AT('^H',t)-1,3))
ENDDO
RETU t

Повторите перевод строки для очистки, найдя ^ H и сделав резервную копию одного символа.


2

Юлия, 41 39 байт

s->foldl((t,v)->chop(t)v,split(s,"^H"))

Он использует ^ H в качестве разделителя, затем удаляет последний символ в каждой строке, затем объединяет следующую строку перед тем, как снова удалить последний символ. В отличие от другого ответа Джулии, это не рекурсивная функция.

Примечание. Я удалил имя функции из определения. Первоначально он сказал, f(s)=а не s->, и вы использовали его как f("AAA^HB^H^H")... но я сохраняю два байта, позволяя ему быть "анонимным", и использую себя в качестве своего имени. Вы используете это так:

(s->foldl((t,v)->chop(t)v,split(s,"^H")))("AAA^HB^H^H")

(вы также можете назначить переменную как f=s->foldl((t,v)->chop(t)v,split(s,"^H")), тогда f("AAA^HB^H^H")будет работать)


2

RS, 8 байт

Технически это не считается, поскольку это зависит от функции, которую я добавил после того, как этот вопрос был опубликован. Тем не менее, я думаю, что это довольно аккуратно.

+?1.\^H/

Живая демоверсия и тестовые случаи .


Является ли новая функция предельной заменой?
xnor

@xnor Да ?1.
kirbyfan64sos

@ Оптимизатор Почему? Вы все равно проигрываете Джема. : O
kirbyfan64sos

Ага :(. Увидел гему после публикации комментария
Оптимизатор

1

Python 2, 74 + 2 = 76 байт

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

n=input();o='';c=0
for l in n:d=l=='^';o=[o+l*(1-c),o[:-1]][d];c=d
print o

4
Откуда эти 2 дополнительных байта?
xnor

Ввод @xnor должен быть заключен в кавычки, чтобы это работало. Я забыл поместить это в пост.
Каде

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

1

Свинка, 84 байта

R Z S T="",Y=$L(Z,"^H") F I=1:1:Y{S T=T_$P(Z,"^H",I) S:I<Y T=$E(T,1,$L(T)-1)} W !,T

Вероятно, это можно сделать как функцию короче (1 байт, который я смог сохранить в быстром тестировании), но мне нравится аспект с одной строкой ... :-)

Брекеты взяты из аромата Mumps из Intersystems Cache, в котором я больше всего разбираюсь.


1

Java - 123 байта

Мне лично эта g---1часть нравится больше всего.

String f(char[] a){String b="";for(int g=-1;++g<a.length;b=(a[g++]=='^'?b.substring(0,b.length()-1):b+a[g---1]));return b;}

расширен (немного):

  String f(char[] a) {
      String b = "";
      for (int g = -1;
           ++g < a.length;
           b = (a[g++]=='^' 
                ? b.substring(0, b.length() - 1) 
                : b + a[g---1])
      );
      return b;
  }

1

Пакет - 138 байт

@!! 2>nul||cmd/q/v/c%0 %1&&exit/b
set s=%1&for /F %%a in ('"prompt $H&echo on&for %%b in (1)do rem"')do set D=%%a
echo %s:^H=!D! !D!%

Первая строка - это способ сохранения нескольких байтов по длине @echo off&setLocal enableDelayedExpansion(который отключает эхо и включает отложенное расширение переменных, если вам интересно). Я объяснил это в Совете по игре в гольф в партии .

Вторая строка - это хитрый маленький трюк для сохранения управляющего символа возврата в переменную. Это довольно глупо, и я не могу притворяться, что взял на себя ответственность за это. Это вроде как объяснено здесь . В основном использует команду prompt, чтобы сгенерировать символ возврата и записать его в переменную - в этом случае !D!.

Последняя строка затем выполняет простую манипуляцию строк - заменить ^Hна !D!<SPACE>!D!.

C:\>bsp.bat "testing^H^H^H test"
"test test"

К сожалению , это порождает такие случаи, как "AAA^HB^H^H"- где он должен производить "A", он вместо этого производит "A"B. Что несколько сбивает с толку. Я должен разобраться, как работает групповая обработка строк, более подробно.

C:\>bsp.bat "AAA^HB^H^H"
"A"B

Благодаря некоторым полезным людям здесь - теперь я понимаю, что я сохранял только символ возврата (0x08) и перезаписывал только символы. Теперь он работает с примерами, подобными следующим:

C:\>bsp.bat "AAA^HB^H^H"
"A"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.