Самая короткая, лексикографически наименьшая генерирующая строка

16

Строка x генерирует строку, yесли yявляется подстрокой бесконечного повторения x. Например abcгенерирует bcabcab.

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

вход

bcabcabca

выход

abc

Самый короткий код выигрывает. Вы можете предположить, что ввод содержит только символы az (и завершающий перевод строки, если хотите).

Кит Рэндалл
источник
Вывод должен быть в любом порядке? Сказать выход можно bacв вашем примере, а не abc?
Муравей
@GroovyUser: нет, входные данные не являются подстрокой повторяющегося шаблона bacs.
Кит Рэндалл
Но входные данные могут состоять из подстроки (bca)^n, что означает bca, что так же верно для данного примера, как abc.
JAB
1
@JAB: bcaне самый маленький лексикографически.
Кит Рэндалл
Ах, я как-то пропустил эту часть.
JAB

Ответы:

9

Ruby 1.9, 40 знаков

gets;a=?a;a.next!until(a*~/$/)[$_];$><<a

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

$ echo -n "bcabcabca" | ruby genlex.rb 
abc
$ echo -n "barfoobarfoobarfoo" | ruby1.9 genlex.rb 
arfoob
Ventero
источник
2

Питон 88 185 символов

import re
s=raw_input()
m=s.index(min(s))
s=s[m:]+s[:m]
i=0
while s.replace(s[:i],''):i+=1
m=min(s[:i])
s=re.findall('%s[\w]*?(?=%s|$)'%(m,m),s[:i])
m=s.index(min(s))
print ''.join(s[m:]+s[:m])

Выход:

bcabcabca
abc

aaa
a

abc
abc

cccbbcccbbcccbb
bbccc

barfoofoobarfoofoo
arfoofoob

bacabac
abacbac
Вейдер
источник
Не дает вам лексикографически наименьшей строки для некоторых входных данных, например, «bacabac»
Howard
@ Говард, ты прав. Я обновил свой код, теперь он намного длиннее, но обрабатывает строки вроде bacabacправильно.
Вейдер
«abac» будет правильным, смотрите ответ @ yogsototh: bacacac abac.
Говард
2

Haskell, 299 128 символов

import Data.List
main=interact(\z->minimum$filter(\w->isInfixOf z$concat$replicate(length z)w) $filter((/=)"")$inits=<<tails z)

Спасибо Джлой! Теперь версия намного короче, и я считаю, что это правильно.

yogsototh
источник
1
Итак, хорошая новость заключается в том, что это решение можно увеличить до 91 символа, если вы принимаете входные данные в stdin, как в решении Ventero для Ruby. К сожалению, ввод cabcabcabcпроизводит abcabc, так что это решение не совсем там. Я думаю, что вам нужно изменить q++q++q, чтобы получить желаемый результат. Моя быстрая попытка починить неровности до 145 символов. (Спойлеры здесь: gist.github.com/1035161 )
Благодарность! Я не знал ни о взаимодействии, ни о начальных << = хвостах, чтобы получить все подстроки. Я немного изменил вашу версию, чтобы получить немного символов. Я удалил сортировку и изменил фильтр (not.null) по фильтру ((/ =) ""). Еще раз спасибо!
Йогсотот
Зачем вам нужно (/=)""состояние? Кажется, он ничего не делает. Также помогает избавление от лямбд: вы можете полностью избавиться от w с помощью .оператора и изменить основную функцию, main=interact sчтобы сохранить пару символов.
Rotsor
Я думаю, что ответ для "BCA" является неправильным. Это должно быть "abc", но сейчас это "bca".
Роцор
Одним из возможных решений является использование permutationsвместо tails.
Роцор
2

Питон, 121 137 129 символов

s=raw_input()
n=len(s)
l=[(s+s)[i/n:i/n+i%n+1]for i in range(n*n)]
print min(filter(lambda x:(x*len(s)).find(s)+1,sorted(l)),key=len)

РЕДАКТИРОВАТЬ: исправлена ​​ошибка, замеченная JiminP

Жюль Оллеон
источник
Вау, это здорово! К сожалению, он печатает aababдля строки ababa... :(
JiminP
Хорошо, исправлено ... это становится длиннее :(
Жюль Оллеон
2

Руби 1.9, 36

$><<(?a..gets).find{|s|(s*~/$/)[$_]}

Использует тот же подход, что и решение Ventero.

Lowjacker
источник
2

Python, 161 159 166 140 141 134 132 символа

y=raw_input();i=n=l=len(y)
while i:
 if (y[:i]*l)[:l]==y:n=i
 i-=1
x=y[:n];y=x*2
while i<n:
 x=min(x,y[i:i+n])
 i+=1
print x

РЕДАКТИРОВАТЬ : Гольф-код после прочтения комментария Жюля Оллеона. Удален «ошибка» , что bcdabcdabприводит к abbc.

EDIT2 : Исправлена ​​ошибка ( abaaрезультаты aaa), замеченная Жюлем Оллеоном.

Я не очень хорошо знаю Python, поэтому этот код, вероятно, «не в гольфе».

Я люблю это правило:

Вы можете предположить, что вход содержит только символы az ...

Входы и выходы

bcdabcd
abcd

bcabcabca
abc


abcdabcd
abcd

bcdabcdab
abcd

barfoofoobarfoofoobar
arfoofoob

cccbbcccbbcccbb
bbccc

aaaaaaaaaaaaaaaa
a

thequickbrownfox
brownfoxthequick

ababa
ab

abaa
aab
JiminP
источник
1
Бурый лис, быстрый! Собака ленивая!
JiminP
Хорошее решение, довольно короткое и, вероятно, лучшая сложность здесь! Вы можете немного поиграть в гольф - например, вам не нужно "int" для сравнения строк; и заменить «while i> 0» на «while i» и «y = y + y» на «y * = 2».
Жюль Оллеон
На самом деле есть проблема: для абаа он печатает ааа ...
Жюль Оллеон
@Jules Спасибо за комментарий! Я не думал об этом ...
JiminP
Вы можете сделать i-=1вместо i=i-1. Аналогично для приращения.
Lowjacker
1

Mathematica 124 байта

x = StringLength@(y = "");
For[i = 1, ! (s = y~StringTake~i)~StringRepeat~x~StringContainsQ~y,i++];
First@Sort@StringPartition[s <> s, i, 1]

Пробелы и символы новой строки (при наличии точек с запятой на концах строк) не имеют смысла в Mathematica и включены сюда для удобства чтения.

Ввод идет между кавычками в первой строке. Если преобразовать как функцию, она принимает строковый ввод примерно так:

f=(x=StringLength@(y=#);For[i=1,!(s=y~StringTake~i)~StringRepeat~x~StringContainsQ~y,i++];First@Sort@StringPartition[s<>s,i,1])&

f@"bca"

(* "abc" *)

f@"abaa"

(* "aab" *)

тогда это 128 байтов.

ForЦикл занимает первые iсимволы на входе и повторяет их , по крайней мере вплоть до длины входа, а затем проверяет , является ли входная подстрока результата. Найдя длину периода строки, StringPartitionкоманда объединяет две копии этого периода и берет из нее все подстроки этой длины (в основном получает все циклические перестановки), а затем First@Sortнаходит первую из них при лексикографическом порядке.

LLlAMnYP
источник
0

javascript 96 символов

var temp = {},len = str.length;
for(i in str) 
temp[str[i]] = true;
Object.keys(temp).join(""); 

Рабочий планкр

ngLover
источник
1
Добро пожаловать в сообщество! Однако я не смог проверить ваш код. Можете ли вы обеспечить чтение кода из GET / POST и запись с помощью alert или console.log или функцию, принимающую входные данные в качестве параметра и возвращающие выходные данные?
Аарон
@AaronGOUZIT добавил pluckr
ngLover
Спасибо, это помогает. Тем не менее, код, который вы разместили, не может использоваться отдельно, так что он обманывает количество байтов. Более того, я боюсь, что ваш код не соответствует спецификациям: я полагаю, что вы возвращаете набор используемых уникальных букв, а не «генерирующую строку», которую мы должны быть в состоянии повторить (в целом) с необязательным усечением до получить вход. Я с нетерпением жду вашего обновленного кода!
Аарон