Медленно превратить строку в другую


31

Соревнование

Учитывая две строки / массив строк, выведите первую строку, медленно сжимающуюся и расширяющуюся обратно во вторую строку.

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

пример

Input:
"Test", "Testing"

Output:
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Сначала вы выводите первое слово:

Test

Затем вы продолжаете удалять одну букву, пока строка не станет длиной в один символ:

Tes
Te
T

Затем продолжайте добавлять одну букву второго слова, пока это не будет сделано:

Te
Tes
Test
Testi
Testin
Testing

(если обе строки имеют длину одного символа, просто выведите одну из них один раз.)

Тестовые случаи

"Hello!", "Hi."
Hello!
Hello
Hell
Hel
He
H
Hi
Hi.

"O", "O"

O

"z", "zz"

z
zz

".vimrc", ".minecraft"

.vimrc
.vimr
.vim
.vi
.v
.
.m
.mi
.min
.mine
.minec
.minecr
.minecra
.minecraf
.minecraft

"     ", "   "

SSSSS
SSSS
SSS
SS
S
SS
SSS

"0123456789", "02468"

0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0
02
024
0246
02468

(примечание: в пробеле / ​​четвертом контрольном примере замените S пробелами)

правила

  • Это , поэтому выигрывает самый короткий ответ в байтах! Tiebreaker - самая популярная публикация. Победитель будет выбран 09.10.2016.

  • Стандартные лазейки запрещены.


Будут ли разрешены 2 конечных символа новой строки (одна видимая пустая строка после последовательности) или нет?
Сешумара

Ответы:


11

Pyth, 9 байт

j+_._Et._

Программа, которая принимает вторую строку, а затем первую строку в виде строк в кавычках в STDIN и печатает результат.

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

Как это работает

j+_._Et._  Program. Inputs: Q, E
   ._E     Yield prefixes of E as a list
  _        Reverse the above
       ._  Yield prefixes of Q as a list (implicit input fill)
      t    All but the first element of above
 +         Merge the two lists
j          Join on newlines
           Implicitly print

14

V , 14 байтов

òYp$xhòjòÄ$xhh

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

Объяснение:

ò     ò     "Recursively:
 Yp         "  Yank the current line and paste it
   $        "  Move to the end of the current line
    x       "  Delete one character
     h      "  Move One character to the right.
            "  Because of the way loops work in V, this will throw an error if there
            "  Is only one character on the current line.

Теперь буфер выглядит так:

0123456789
012345678
01234567
0123456
012345
01234
0123
012
01
0

Нам просто нужно сделать то же самое в обратном порядке для следующей строки:

j           "Move down one line
 ò     ò    "Recursively (The second ò is implicit)
  Ä         "  Duplicate this line up
   $        "  Move to the end of the current line
    x       "  Delete one character
     hh     "  Move two characters to the right.
            "  Because of the way loops work in V, this will throw an error if there
            "  Is only two characters on the current line.

Более интересное альтернативное решение :

òÄ$xhòç^/:m0
ddGp@qd

3
Это как будто vim всегда правильный инструмент для работы
Downgoat

@ Downgoat Точно. Вот почему вы должны начать играть в гольф в V.: P
DJMcMayhem

9

Python, 93 байта

f=lambda a,b,r='',i=2:a and f(a[:-1],b,r+a+'\n')or(len(b)>=i and f(a,b,r+b[:i]+'\n',i+1)or r)

Начинается с пустой строки r, добавляет aи новую строку и удаляет последний символ aдо тех пор, пока он не aстанет пустым, затем добавляет требуемые части bи новую строку , сохраняя счетчик i, который начинается с 2тех пор, пока не bбудет превышена длина , а затем вернется r. Имеет завершающий перевод строки.

Все тесты на ideone


2 вещи. 1) Я считаю, что вы неправильно подсчитали персонажей, и это на самом деле 93 и 2) Вам не нужно говорить r="". Простой rвсе равно будет работать.

Спасибо @JackBates. 1. Исправьте и обновите - я наверное забыл f=. 2. Без r=''настоящего f('test','testing')не будет работать; да f('test','testing',''), но мы должны следовать спецификациям.
Джонатан Аллан

Прости меня. Я просто смотрю на код, а не на примеры.


7

Retina, 50 41 26 байт

Спасибо Мартину Эндеру за сохранение 15 (!) Байтов.

M&!r`.+
Om`^.¶[^·]+|.+
A1`

Принимает ввод с двумя строками, разделенными новой строкой:

Test
Testing

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

объяснение

M&!r`.+

Первая строка генерирует «шаги» обоих слов:

Testing
Testin
Testi
Test
Tes
Te
T
Test
Tes
Te
T

Mпредназначен для режима совпадения, &учитывает перекрывающиеся совпадения и !печатает совпадения вместо их количества. Причина, по которой он меняется на противоположный, - rопция «направо-налево»: двигатель начинает поиск совпадений в конце строки и продолжает движение к началу.

Om`^.¶[^·]+|.+

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

A1`

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

Старая версия

M&!r`.+
O`\G..+¶
s`(.*)¶.¶(.*)
$2¶$1
¶.$

Попробуйте эту версию онлайн!

объяснение

Первая строка такая же, поэтому смотрите объяснение этому выше.

O`\G..+¶

Это переворачивает строки первой половины (второго входного слова). На самом деле Oэто строки, а регулярное выражение ограничивает совпадения: это должна быть строка из двух или более символов ( ..+), за которой следует символ новой строки ( ), начинающийся там, где остановился последний ( \G). В приведенном выше примере сингл Tв середине не совпадает, так что ничего после этого не может.

Te
Tes
Test
Testi
Testin
Testing
T
Test
Tes
Te
T

Теперь у нас есть правильные два компонента, но в неправильном порядке.

s`(.*)¶.¶(.*)
$2¶$1

¶.¶соответствует одиночке T посередине, которая нам не нужна, но разделяет две части. Они (.*)захватывают все до и после, в том числе и sновые строки благодаря режиму сингла. Два снимка заменяются в правильном порядке с новой строки между ними.

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


4

Python 2, 88 82 байта

x,y=input(),input()
for i in x:print x;x=x[:-1]
s=y[0]
for i in y[1:]:s+=i;print s

Принимает два входа, каждый в кавычках.

Спасибо @JonathanAllan за сохранение некоторых байтов и указание на ошибку.


1
Нет необходимости len(x)в x=x[:len(x)-1]In, так как срезы с отрицательным смещением работает - вы можете просто написать x=x[:-1]. Единственная проблема в том, что ваш код не " ", " "очень хорошо справляется с тестовым примером.
Джонатан Аллан

1
Вы можете отбросить второй input()и использовать формат ввода, например"<str1>", "<str2>"
LevitatingLion

Вы можете изменить вторую строку на for i in range(x):print x[-i:], а четвертую строку на for i in range(1,y):print y[:-i]. Не уверен, что это сработает.
clismique

4

Perl, 34 28 байт

Включает +2в себя для-0n

Запустите строки в отдельных строках на STDIN:

perl -M5.010 -0n slow.pl
Test
Testing
^D

slow.pl:

/(^..+|
\K.+?)(?{say$&})^/

Пусть regex backtracking сделает всю работу ...



3

Брахилог , 32 байта

:1aLtT,Lhbr:Tc~@nw
:2fb
~c[A:B]h

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

объяснение

Brachylog не имеет встроенного префикса, поэтому мы получим префиксы с помощью concatenate(См. Предикат 2): префикс Sis, Pесли Pобъединяется с Q(каким бы он ни был), приводит к S.

  • Основной предикат:

    :1aL                  L is all prefixes of both elements of the input (see predicate 1)
       LtT,               T is the second element of L
           Lhbr           Remove the first prefix of the first list of L and reverse it
               :Tc        Concatenate with T
                  ~@n     Join with newlines
                     w    Write to STDOUT
    
  • Предикат 1:

    :2f                   Find all prefixes of the input string (see predicate 2)
       b                  Remove the first one (empty string)
    
  • Предикат 2:

    ~c[A:B]               Input is the result of concatenating A to B
           h              Output is A
    

3

Javascript, 103 81 байт

f=(x,y,n=1)=>x?`
`+x+f(x.slice(0,-1),y):n++<y.length?`
`+y.slice(0,n)+f(x,y,n):''

Пример: f("Test", "Testing")

Выход:

Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Оригинальный ответ

f=(x,y,n=1)=>x?(console.log(x),f(x.slice(0,-1),y)):n++<y.length?(console.log(y.slice(0,n)),f(x,y,n)):''

3

Ява, 188 179 байт

interface E{static void main(String[]a){int i=a[0].length();while(i>1)System.out.println(a[0].substring(0,i--));while(i<=a[1].length())System.out.println(a[1].substring(0,i++));}}

Обновить

  • Удалена переменная s, сохранено 9 байт.

Ungolfed :

interface E {

    static void main(String[] a) {
        int i = a[0].length();
        while (i > 1) {
            System.out.println(a[0].substring(0, i--));
        }
        while (i <= a[1].length()) {
            System.out.println(a[1].substring(0, i++));
        }
    }
}

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

$ java E 'test' 'testing'
test
tes
te
t
te
tes
test
testi
testin
testing

3

Haskell, 54 53 47 байт

t[]=[]
t x=x:t(init x)
(.reverse.t).(++).init.t

Пример использования: ((.reverse.t).(++).init.t) "Hello" "Hi!"-> ["Hello","Hell","Hel","He","H","Hi","Hi!"].

Некоторая бессмысленная магия. Это то же самое, что и f x y = (init(t x))++reverse (t y)где tсоставляется список всех исходных подстрок, например t "HI!"-> ["H","HI","HI!"].


Хм t=reverse.tail.inits?
Берги

@ Берги: конечно, но initsнужно import Data.List.
Nimi


3

GNU sed, 57 45 + 2 (рН-флаги) = 47 байт

:;1{/../p};2G;2h;s/.(\n.*)?$//;/./t;g;s/.$//p

Бег:

echo -e "Test\nTesting" | sed -rnf morphing_string.sed

На входе должны быть две строки, разделенные новой строкой. Код запускается с помощью sed для каждой строки.

Цикл :итеративно удаляет один символ из конца строки. Выход связан с первой строки печатается непосредственно, за исключением первого символа: 1{/../p}. Вывод для второй строки сохраняется во 2G;2hвремя удаления в обратном порядке ( ) во время удаления и печатается в конце.


3

C (gcc) , 102 97 95 93 байта

n;f(char*a,char*b){for(n=strlen(a);n;puts(a))a[n--]=0;for(a=b+1;*a++;*a=n)n=*a,*a=0,puts(b);}

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

Первый цикл перезаписывает строку с 0 байтами, начиная с конца, и использует ее puts()для печати строки. Второй цикл не может просто перезаписать с самого начала, он должен хранить старое значение, чтобы он мог вернуть его обратно; 0 байт просто идет к концу.

Спасибо @homersimpson и @ceilingcat за каждое бритье на 2 байта!


1
Вы можете сэкономить пару байт, объявляя в nкачестве глобального междунар как: n;f(char*a,char*b){n=strlen(a).... И вы, вероятно, можете сделать это n=*a=0как цепочечное задание в теле вашего цикла for.
homersimpson

Спасибо @homersimpson. Но n = * a = 0 - это не то же самое, что n = * a, * a = 0.
Г. Слипен

2

Python 3, 104 байта

Мех.

n='\n';lambda x,y:x+n+n.join(x[:-i]for i in range(1,len(x)-1))+n+n.join(y[:i]for i in range(1,len(y)+1))

Спасибо @DJMcMayhem за игру в гольф на 21 байт.

Идео это!


1
Вы можете взять 5 байтов, если вы делаете n='\n'и использовать n вместо '\n'. Вы могли бы снять еще 8, если бы вместо печати использовали лямбду:n='\n';lambda x,y:n.join(x+n+n.join(x[:-i]for i in range(1,len(x)-1))+n+n.join(y[:i]for i in range(1,len(y)+1)))
DJMcMayhem

2

REPL / Javascript, 109 байт

Использует ложную строку, чтобы уменьшить исходную строку

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

(a,b)=>{l=console.log;z='substring';for(c=a.length;d=a[z](0,c--);){l(d)}for(c=2;d!=(n=b[z](0,c++));){l(d=n)}}

Демо-версия:

> ((a,b)=>{l=console.log;z='substring';for(c=a.length;d=a[z](0,c--);){l(d)}for(c=2;d!=(n=b[z](0,c++));){l(d=n)}})("asdf","abcd")
[Log] asdf
[Log] asd
[Log] as
[Log] a
[Log] ab
[Log] abc
[Log] abcd

1
это на 1 байт короче, чтобы сделать a=>b=>...и вызвать функцию с (a) (b)
Zwei

2

Brainfuck, 38 55 байт

>++++++++++>,[>,]<[<]>>[[.>]<[-]<[<]>.>],.[[<]>.>[.>],]

Изменить: включены новые строки в выводе


Я не могу заставить твой код работать. Разделен ли ввод новой строкой? Какой переводчик вы используете?
Акролит


2

Ракетка 193 байта

(define(f l)
(let*((s(list-ref l 0))
(x(string-length s)))
(for((n x))
(println(substring s 0(- x n))))
(set! s(list-ref l 1))
(for((n(range 1(string-length s))))
(println(substring s 0(add1 n))))))

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

(f(list "Test" "Testing"))

"Test"
"Tes"
"Te"
"T"
"Te"
"Tes"
"Test"
"Testi"
"Testin"
"Testing"


(f(list "Hello!" "Hi."))

"Hello!"
"Hello"
"Hell"
"Hel"
"He"
"H"
"Hi"
"Hi."

Следует удалить последний символ из входной строки, а не первый.
Агилоб

2

Флорид , 69 байт

a,b=L.J
c=1
NZ(a)!=1:z(a);a=a[:-1]
z(a)
NZ(a)!=Z(b):c+=1;a=b[:c];z(a)

Это начало. Принимает вход от STDIN.

Testcases

Input: Test Testing
Output:
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Input: O O
Output: O

1

JavaScript (ES6), 92 байта

(s,t)=>s.replace(/./g,`
$\`$&`).split`
`.slice(2).reverse().join`
`+t.replace(/./g,`
$\`$&`)

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

(s,t)=>s.replace(/./g,`
$\`$&\n`).split(/^/m).slice(1).reverse().join``+t.replace(/./g,`
$\`$&\n`)

1

C, 142 байта

#define _(x,y) while(y)printf("%.*s\n",d,x-c);
f(char*a,char*b){int c=1,d=strlen(a)+1;while(*++a==*++b)c++;_(a,--d>=c)d++;_(b,d++<strlen(b-c))}

Обеспечить f(char* str1, char* str2).


1

TI-Basic, 56 байт

Prompt Str1,Str2
Str1
While 1<length(Ans
Disp Ans
sub(Ans,1,length(Ans)-1
End
For(I,1,length(Str2
Disp sub(Str2,1,I
End

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

Str1=?Test
Str2=?Testing
Test
Tes
Te
T
Te
Tes
Test
Testi
Testin
Testing

Str1=?O
Str2=?O
O

Str1=?z
Str2=?zz
z
zz

1

Ява, 168 136 байт

(s,d)->{int i=s.length()+1;while(i-->1)System.out.println(s.substring(0,i));while(i++<d.length())System.out.println(d.substring(0,i));};

Тестовая программа Ungolfed

public static void main(String[] args) {

    BiConsumer<String, String> biconsumer = (s, d) -> {
        int i = s.length() + 1;
        while (i-- > 1) {
            System.out.println(s.substring(0, i));
        }
        while (i++ < d.length()) {
            System.out.println(d.substring(0, i));
        }
    };

    biconsumer.accept("Test", "Testing123");

}

1

(Lambdabot) Haskell - 41 байт

f=(.drop 2.inits).(++).reverse.tail.inits

Более читаемый, но на два байта длиннее:

a!b=(reverse.tail$inits a)++drop 2(inits b)


Выход:

f "Hello" "Hi!"
["Hello","Hell","Hel","He","H","Hi","Hi!"]

1

J, 18 байт

]\@],~[:}:[:|.]\@[

Ungolfed:

]\@] ,~ [: }: [: |. ]\@[

Это 7 поезд

]\@] ,~ ([: }: ([: |. ]\@[))

Самая внутренняя [: |. ]\@[последовательность состоит из верхнего колпачка [:слева, поэтому мы применяем |.(реверс) к результату ]\@[, который является ]\(префиксы) над [(левый аргумент).

Вот как это выглядит на testing, testвходе:

   'testing' ([: |. ]\@]) 'test'
test
tes
te
t

Это дает нам первую порцию, почти. 5-поезд вне этого ([: }: ([: |. ]\@[)), который применяется }:(betail, удалить последний элемент) к вышеприведенному выражению:

   'testing' ([: }: [: |. ]\@]) 'test'
test
tes
te

(Это потому, что у нас не может быть дубликата средней точки.)

Внешняя часть наконец-то:

]\@] ,~ ([: }: ([: |. ]\@[))

Это состоит из ]\@](префиксы левого аргумента) и ,~(добавьте то, что слева, а что справа), оставляя нам желаемый результат:

   'testing' (]\@] ,~ ([: }: ([: |. ]\@[))) 'test'
testing
testin
testi
test
tes
te
t
te
tes
test

Контрольные примеры

   k =: ]\@] ,~ ([: }: ([: |. ]\@[))
   'o' k 'o'
o
   k~ 'o'
o
   'test' k 'test'
test
tes
te
t
te
tes
test
   k~ 'test'
test
tes
te
t
te
tes
test
   '. . .' k '...'
. . .
. .
. .
.
.
..
...
   'z' k 'zz'
z
zz

Вы можете изменить его на 14 байтов, используя(,~}:@|.)&(]\)
миль

1

PHP, 117 109 байт

for($i=strlen($a=$argv[1]);$i>1;)echo" ".substr($a,0,$i--);
for(;$j<strlen($b=$argv[2]);)echo" ".$c.=$b[$j++];

for($i=strlen($a=$argv[1]);$i>1;)echo substr($a,0,$i--)." ";
for(;$i<=strlen($b=$argv[2]);)echo substr($b,0,$i++)." ";

PHP, 107 байт (не работает со строками, содержащими 0)

for($a=$argv[1];$a[$i];)echo substr($a.a,0,-++$i)." ";
for($b=$argv[2];$b[$j];)echo substr($b,0,++$j+1)." ";

1

C 111 байтов

f(char*a, char*b){int l=strlen(a),k=1;while(*a){printf("%s\n",a);a[--l]=0;}while(b[k]) printf("%.*s\n",++k,b);}

Тест на недолговечность

#include <stdio.h>
#include <string.h>

f(char*a, char*b) {
  int l=strlen(a), k=1;
  while(*a) {
    printf("%s\n",a);
    a[--l]=0;
  }
  while(b[k])
    printf("%.*s\n",++k,b);
}

int main() {
  char a[10] = {0};
  char b[10] = {0};

  for (int i=0; i<5; ++i) {
    a[i] = 'a' + i;
    b[i] = 'a' + i*2;
  }

  f(&(a[0]), &(b[0]));
}

1

брейкфук, 162 байта

,[>,]++++++++++[[-<]>[->]<]++++++++++[<[+<]<[+<]>[+>]>[+>]<---]<[<]<[<]>[[.>]++++++++++.----------<[-]<[[->+<]<]>>]>[<+>-]>[[<+>-]<[<]>[.>]++++++++++.---------->]

Попробуй здесь

Ввод принимает две строки, разделенные переводом строки.

Первая программа с brianfuck и первым гольф-кодом, так что я уверен, что предстоит много оптимизации. Хотя было весело делать это.

Ungolfed

,[>,] Read all input
++++++++++ Flag for 10
[                   Subtract 10 from each cell to flag space for blank
    [-<]            
    >
        [->]
        <
]
++++++++++ Flag for 10
[                   Add 10 back to each cell with value in it
    <[+<]<[+<]
    >[+>]>[+>]<---
]
<[<]<[<]>               goto first cell in first string string      

[                           Print first word subtracting one each time
    [.>]                    Print first string
    ++++++++++.----------   Print new line
    <[-]                    Kill last letter of first string
    <                       Back one
    [                       Move each first string character up one
          [->+<]
          <
    ]>>
]
>[<+>-]>                    Move to first letter of scond string back one goto second letter
[                               
    [<+>-]                  Move next letter back
    <[<]>                   Move to start of string
    [.>]                    Print string
    ++++++++++.----------   Print new line
    >
]

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