Розгорнути вкладки (впровадити розширення (1))


10

На цей раз ваше завдання - реалізувати варіант expand(1)утиліти POSIX , який розширює вкладки на пробіли.

Ваша програма повинна взяти специфікацію табулятора, а потім прочитати введення на стандартному в і замінити символи вкладки на вхід на відповідну кількість пробілів, щоб дістатися до наступного стоп-стопу. Результат слід записати на стандартне оформлення .

Специфікація Tabstop

Специфікація табуляції складається або з одного числа, або розділеного комами списку табуляції. У випадку одиничного числа воно повторюється так, ніби кратні його трапляються у списку, розділеному комами (тобто 4діє як 4,8,12,16,20,...). Кожен запис у списку, розділеному комами, є додатним цілим числом, необов'язково префіксом a +. +Префікс вказує на відносну різницю до попереднього значення в списку через кому. Перше значення у списку має бути абсолютним (тобто нефіксованим). Вкладки вказують стовпчик наступного непробільного символу (слідом за розширеною вкладкою), причому крайній лівий стовпець вважається числом 0. Вкладки повинні завжди розширюватися принаймні до одного пробілу.

Введення-виведення

Специфікація tabstop або повинна сприйматися як перший параметр командного рядка для програми, або читатися зі стандарту в якості першого рядка введення (закінчується новим рядком) на ваш розсуд. Після того, як зчитується табло стоп, обробляється та розширюється залишився вхід (весь вхід, у першому випадку) до EOF. Розширений вихід виписується до стандартного.

Всі розгорнуті вкладки та всі вхідні дані передбачаються максимум 80 стовпцями. Всі розгорнуті вкладки суворо збільшуються.


Приклад

Специфікація Tabstop 4,6,+2,+8еквівалентна 4,6,8,16і з обома вхідними

ab<Tab>c
<Tab><Tab>d<Tab>e<Tab>f

розгорнуто на ( вказує пробіл)

ab␣␣c
␣␣␣␣␣␣d␣e␣␣␣␣␣␣␣f

01234567890123456   (Ruler for the above, not part of the output)
          1111111

Зарахування - чистий ; виграє найкоротший код.

Відповіді:


2

GolfScript ( 77 75 символів)

n/(','/{'+'/{~t++}*~:t}%81,{t*}%+:T;{[0\{.9={;T{1$>}?(.)@-' '*}*\)}/;]n+}/;

Я дуже задоволений розбором tabspec.

# Split on commas
','/
# For each element:
{
    # Split on '+'
    '+'/
    # We now have either ["val"] or ["" "val"]
    # The clever bit: fold
    # Folding a block over a one-element array gives that element, so ["val"] => "val"
    # Folding a block over a two-element array puts both elements on the stack and executes,
    # so ["" "val"]{~t++}* evaluates as
    #     "" "val" ~t++
    # which evaluates val, adds the previous value, and concatenates with that empty string
    {~t++}*
    # Either way we now have a string containing one value. Eval it and assign to t
    ~:t
}%

Потім я додаю кратні елементи останнього елемента, поки мені гарантовано вистачить, щоб досягти кінця 80 стовпців:

81,{t*}%+

Це дає бажану поведінку, коли був вказаний лише один табстоп, а в іншому випадку є релевантним лише у випадках, коли специфікація не згадує. (Зауважте, що він робить список зупинок табуляцій назад до 0, а потім повторює останній проаналізований елемент, але це не має значення, оскільки якщо мова йде про використання списку, я шукаю перший елемент більший за поточне положення).

Решта досить просто.


2

Рубі 161 145

Читає специфікацію табулятора в першому рядку введення.

i=t=[]
gets.scan(/(\+)?(\d+)/){t<<i=$2.to_i+($1?i:0)}
81.times{|j|t<<j*i}
while gets
$_.sub!$&," "*(t.find{|s|s>i=$`.size}-i)while~/\t/
print
end

редагування: Додано два рядки, що робить повторне читання останнього прочитаного табустопату, щоб специфікації табстоп для одного номера також працювали правильно

iє тимчасовою змінною для утримання останнього проаналізованого табустопа. t- це список таблиць вкладок, розібраний з gets.scanрядка. Для гарної міри додаємо 81 кратну частину останнього проаналізованого табустопа. while getsцикл продовжує йти до тих пір, поки більше немає введення. Для кожного рядка введення ми підміняємо вкладки пробілами, одна вкладка одночасно, тому що рядок рухається, коли ми додаємо пробіли, і ми повинні перерахувати правильний стоп вкладки.


Я не знаю Рубі, але ти можеш писати x+($1?i:0)як коротше $1?x+i:x?
Тімві

@Timwi Nope! Рубі трохи дивно з термінальним оператором. Зазвичай потрібно десь помістити пробіл, оскільки двокрапка ( :) також може означати початок символу , але оскільки символ не може починатися з цифри, :0це нормально без пробілу. Або щось. Це дивно. Дуже важливі також дужки.
daniero

Це сканування на вкладці мені здається баггі. У t<<x+($1?i:0);i=xпершому твердженні не змінюється x, чи не так? Я думаю, вам потрібно перетворити це якi=x+($1?i:0);t<<i
Пітер Тейлор

1
Насправді ви можете зберегти 16, замінивши перші два рядки на i=t=[](оскільки iгарантовано, що вони не знадобляться вперше); спрощення синтаксичного розбору табуляції {t<<i=$2.to_i+($1?i:0)}та усунення lповністю ( iце значення вже утримується). Але приємно, що не піклуватися про вкладку, перестаньте суворо збільшуватися: це заощаджує 4 символи, і я можу позичити це для економії 2.
Пітер Тейлор

@PeterTaylor Дякую за вклад! Це не було безпосередньо баггі, але, звичайно, трохи роздуто. Я вважаю, що занадто просто дивитись на себе сліпим на такий код.
daniero

1

C, 228 символів

Ось рішення C, щоб розпочати справи. Тут ще багато займатися гольфом (подивіться на всі ці ifі forз і putcharз ...). Перевірений на прикладі тестової скриньки, а також з тим же входом, але 4і 8для специфікації вкладок.

S[99],i;L,C;main(v){for(v=1;v;)v=scanf("+%d",&C),v=v>0?C+=L:scanf("%d",&C),
v&&(S[L=C]=++i,getchar());for(;i==1&&C<80;)S[C+=L]=1;for(C=L=0;C=~getchar();)
if(C+10)putchar(~C),L+=C+11?1:-L;else for(putchar(32);!S[++L];)putchar(32);}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.