Інтерпретувати /// (вимовляється 'косої риски')


30

Тому що ми не можемо отримати достатню кількість езотеричних мовних гольфів, чи не можемо?

/// - яскраво виражені косої риси - це весела маленька мова, заснована на s///функції заміни регулярних виразів слави Perl. Він містить лише два спеціальних символи, косу /рису нахилу та нахил \. Ви можете знайти повну статтю про неї на вікі esolangs , але я відтворять опис мови нижче, а також деякі приклади.

Коротше кажучи, він працює, ідентифікуючи /pattern/repl/restв програмі та здійснюючи заміну якомога більше разів. Жодні символи не є спеціальними, за винятком /та \: /демаркація шаблонів та замін у програмі, в той час як \дозволяє вставляти буквальні /чи \символи у свій код. Зокрема, це не регулярні вирази, а просто підміна рядків.

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

Ви можете використовувати будь-яку мову, крім ///. Ви не можете використовувати будь-які бібліотеки, що інтерпретують ///; Ви можете, однак, використовувати регекси, бібліотеки регулярних виразів або бібліотеки, що відповідають строкам.


Виконання

Є чотири стани, друк , шаблон , заміна та заміна . У кожному штаті, крім заміни :

  • Якщо програма порожня, виконання зупиняється.
  • В іншому випадку, якщо перший символ є \, зробіть щось із наступним символом (якщо він присутній) і видаліть обидва з програми.
  • В іншому випадку, якщо перший символ є /, видаліть його та перейдіть до наступного стану.
  • Інше, зробіть щось із першим символом і видаліть його з програми.
  • Повторіть.

Стани проходять цикл друку , шаблону , заміни та заміни в порядку.

  • У режимі друку "зробіть щось" означає виведення символу.
  • У режимі візерунка "зробіть щось" означає додавання символу до поточного шаблону.
  • У режимі заміни "зробіть щось" означає додавання символу до поточної заміни.

У режимі заміни ви дотримуєтесь іншого набору правил. Неодноразово замінюйте перше виникнення поточного Шаблону поточною Заміною в програмі, доки більше не можливі заміни. Після цього очистіть "Шаблон" та "Заміна" та поверніться до режиму друку .

У програмі /foo/foobar/foo foo fooвідбувається таке:

/foo/foobar/foo foo foo
foo foo foo
foobar foo foo
foobarbar foo foo
foobarbarbar foo foo
...

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


Приклади

no

Вихід: no.

/ world! world!/Hello,/ world! world! world!

Вихід: Hello, world!.

/foo/Hello, world!//B\/\\R/foo/B/\R

Вихід: Hello, world!.

a/ab/bbaa/abb

Вихід: a. Програма не зупиняється.

//

Вихід: немає.

///

Вихід: немає. Програма не зупиняється.

/\\/good/\/

Вихід: good.

На вікі також є квін, який можна спробувати.


/-/World//--/Hello//--W/--, w/---!Що не любити? (Спробуйте видалити тире з кінця)
seequ

@Loovjo Герой \ уникає будь-якого персонажа, який слідує за ним, у тому числі /, який згодом може бути використаний як звичайний. Хоча це виглядає не так вже й багато, це робить /// Turing-завершеним .
Алгоритм

Я думаю, що це краще пояснення мови, ніж стаття вікі esolangs. Буде використовувати цю інформацію в моєму ///IDE, що я роблю!
clabe45

Відповіді:


7

APL (133)

{T←''∘{(0=≢⍵)∨'/'=⊃⍵:(⊂⍺),⊂⍵⋄(⍺,N⌷⍵)∇⍵↓⍨N←1+'\'=⊃⍵}⋄⍞N←T⍵⋄p N←T 1↓N⋄r N←T 1↓N⋄''≡N:→⋄∇{⍵≡p:∇r⋄∨/Z←p⍷⍵:∇(r,⍵↓⍨N+≢p),⍨⍵↑⍨N←1-⍨Z⍳1⋄⍵}1↓N}

Це функція, яка приймає ///код як правильний аргумент.

Безумовно, з поясненням:

slashes←{
   ⍝ a function to split the input string into 'current' and 'next' parts,
   ⍝ and unescape the 'current' bit
   split←''∘{
       ⍝ if the string is empty, or '/' is reached,
       ⍝ return both strings (⍺=accumulator ⍵=unprocessed)
       (0=≢⍵)∨'/'=⊃⍵:(⊂⍺),⊂⍵
       ⍝ otherwise, add current character to accumulator,
       ⍝ skipping over '\'s. (so if '\/' is reached, it skips '\',
       ⍝ adds '/' and then processes the character *after* that.)
       idx←1+'\'=⊃⍵
       (⍺,idx⌷⍵)∇idx↓⍵
   }

   ⍞   next ← split ⍵      ⍝ output stage
   pat next ← split 1↓next ⍝ pattern stage, and eat the '/'
   rpl next ← split 1↓next ⍝ replacement stage, and eat the '/'

   ⍝ if there are no characters left, halt.
   ''≡next:⍬

   ⍝ otherwise, replace and continue.
   ∇{  ⍝ if the input string equals the pattern, return the replacement and loop
       ⍵≡pat:∇rpl

       ⍝ otherwise, find occurences, if there are, replace the first and loop
       ∨/occ←pat⍷⍵:∇(rpl, (idx+≢pat)↓⍵),⍨ (idx←(occ⍳1)-1)↑⍵

       ⍝ if no occurences, return string
       ⍵

   }1↓next
}

"якщо символів не залишилося, зупиніться." Чи правильно це працює на ///і //foo/(тобто петлі назавжди)?
алгоритм

@algorithmshark: так, у цій ситуації /все-таки залишилися б на цьому етапі.
marinus

11

J - 181 190 170 char

Це був кошмар. Я переписав його з нуля, двічі, тому що він мене просто клопотав. Це функція, яка бере аргумент одного рядка, виводить на STDOUT.

(0&$`((2{.{:@>&.>)((j{.]),-i@=`p@.~:~/@[,]}.~#@p+j=.0{p I.@E.])i 5;@}.&,'/';"0;&.>)@.(2<#)@}.[4:1!:2~{:@>@p=.>@{.@[)@((0;(0,:~1 0,.2);'\';&<1 0)<;._1@;:'/'&,)i=. ::](^:_)

Щоб пояснити, я розбиваю його на пізнання.

i =. ::](^:_))
parse =: ((0;(0,:~1 0,.2);'\';&<1 0)<;._1@;:'/'&,)
print =: 4:1!:2~{:@>@p=.>@{.@[
eval  =: 0&$`((2{.{:@>&.>)sub 5;@}.&,'/';"0;&.>)@.(2<#)@}.
sub   =: ((j{.]),-i@=`p@.~:~/@[,]}.~#@p+j=.0{p I.@E.])i

interp =: (eval [ print) @ parse i
  • i(скорочення - повторення ) - прислівник. Він бере аргумент дієслова зліва і повертає дієслово (f)i, яке при застосуванні до аргументу fнеодноразово застосовується до аргументу, поки не трапиться одна з двох речей: він знаходить фіксовану точку ( y = f y) або видає помилку. Поведінка з фіксованою точкою властива ^:_і ::]обробці помилок.

  • parseтокенізує вхід у те, що я називаю напівпроаналізованою формою, а потім розрізає його на незміненому "/". Він прив'язує косої нахили до своїх персонажів, але не позбавляється від косої риси, тому ми можемо або повернути її, або закінчити в залежності від того, що хочемо.

    Основна частина цікавого твору відбувається в ;:. Це примітивний машинний інтерпретатор, який описує машину ( (0;(0,:~1 0,.2);'\';&<1 0)) зліва і щось розбирає праворуч. Це робить токенізацію. Зауважу, що ця конкретна машина насправді ставиться до першого символу неспеціально, навіть якщо він є \і повинен зв’язувати. Я роблю це з кількох причин: (1) таблиця стану простіша, тому її можна додатково грати в гольф; (2) ми можемо просто додати манекена на фронт, щоб уникнути проблеми; і (3) цей персонаж манекена отримує напівпроаналізований без зайвих витрат, тому я можу використовувати його для встановлення наступного етапу різання.

    Ми також використовуємо <;._1для того, щоб вирізати токенізований результат на недиспансеризованому /(саме це я і вибрав першим знаком). Це зручно для виведення результатів, шаблону та заміни з out/patt/repl/restусіх за один крок, але, на жаль, також скорочує решту програми, де нам потрібні ті, /що залишаються недоторканими. Я зрощую їх назад під час eval, тому що, якщо <;._1залишити їх в спокої, це коштує набагато дорожче.

  • Вилка (eval [ print)виконує printрезультат з parseбоку для своїх побічних ефектів, а потім запускається eval. printце просте дієслово, яке відкриває перше поле (те, про яке ми точно знаємо, є вихідним), закінчує його розбір і відправляє в STDOUT. Однак ми також ризикуємо визначити дієслово утиліти p.

    pвизначається як >@{.@[, тому він бере лівий аргумент (діє як ідентичність, якщо дається лише один аргумент), бере перший елемент цього (ідентифікація, коли надається скаляр), і розпаковує його (ідентифікація, якщо вона вже є без коробки). Це стане дуже корисним у sub.

  • evalоцінює залишок оброблюваної програми. Якщо у нас немає повного шаблону або повної заміни, evalвін викидає його та просто повертає порожній список, який припиняє оцінку, роблячи ;:parse) помилку на наступній ітерації. В іншому випадку, evalповністю аналізує шаблон і заміну, виправляє залишок джерела, а потім передає обидва sub. Вибухом:

                                                  @}.  NB. throw out printed part
                                           @.(2<#)     NB. if we have a pattern and repl:
          2{.                                          NB.  take the first two cuts:
                 &.>                                   NB.   in each cut:
             {:@>                                      NB.    drop escaping \ from chars
         (          )                                  NB.  (these are pattern and repl)
                                       &.>             NB.  in each cut:
                                      ;                NB.   revert to source form
                                '/';"0                 NB.  attach a / to each cut
                              &,                       NB.  linearize (/ before each cut)
                         5  }.                         NB.  drop '/pattern/repl/'
                          ;@                           NB.  splice together
        (            sub                  )            NB.  feed these into sub
       `                                               NB. else:
    0&$                                                NB.  truncate to an empty list
    
  • subде відбувається один (можливо нескінченний) раунд заміни. Через спосіб, який ми налаштували eval, джерело є правильним аргументом, а шаблон і заміна з'єднуються разом зліва. Оскільки аргументи впорядковані так, і ми знаємо, що шаблон і заміна не змінюються в рамках раунду підстановок, ми можемо використовувати ще одну особливість i- той факт, що він модифікує лише правильний аргумент і продовжує передавати в той же лівий - для делегування до J необхідність турбуватися про відстеження стану.

    Однак є дві плями біди. Перший полягає в тому, що дієслова J можуть мати максимум два аргументи, тому ми не маємо простий спосіб отримати доступ до будь-якого, що поєднуються разом, як шаблон і заміна. Завдяки розумному використанню pутиліти, яку ми визначили, це не є великою проблемою. Насправді, ми можемо отримати доступ до шаблону в одному символі, просто використовуючи p, через його >@{.@[визначення: Unbox Першого пункту зліва аргумент. Отримати заміну складніше, але найкоротший спосіб був би p&|.- на 2 символи коротший, ніж витягнути його вручну.

    Друга проблема полягає в тому, що iвиходить з фіксованих точок, а не циклічно назавжди, і якщо шаблон і заміна є рівними, і ви здійснюєте заміну, це схоже на фіксовану точку до Дж. якщо ми виявимо, що вони рівні: це -i@=`p@.~:~/частина, що замінює p&|..

                                        p    E.]    NB. string search, patt in src
                                          I.@       NB. indices of matches
                                      0{            NB. take the first (error if none)
                                   j=.              NB. assign to j for later use
                               #@p+                 NB. add length of pattern
                           ]}.~                     NB. drop that many chars from src
                       /@[                          NB. between patt and repl:
                      ~                             NB.  patt as right arg, repl as left
                  @.~:                              NB.  if equal:
            -i@=                                    NB.   loop forever
                `p                                  NB.  else: return repl
     (j{.])                                         NB. first j chars of src
           ,              ,                         NB. append all together
    (                                           )i  NB. iterate
    
  • Цей цикл повторюється завдяки використанню i, поки не з’явиться щось поза subпомилками. Наскільки мені відомо, це може статися лише тоді, коли ми не маємо символів, коли ми викидаємо неповний набір заміни шаблону та заміни.

Веселі факти про цей гольф:

  • Один раз використання ;:коротше, ніж вручну ітерація через рядок.
  • 0{повинен мати шанс помилитися, перш ніж subперейде в нескінченний цикл, тому це має спрацювати нормально, якщо шаблон відповідає заміні, але ніколи не відображається в решті джерела. Однак це може бути, а може, і не бути визначеною поведінкою, оскільки я не можу знайти жодне цитування в документах. Whoopsie.
  • Перерви на клавіатурі обробляються як спонтанні помилки всередині запущених функцій. Однак через характер iцих помилок потрапляють і в пастку. Залежно від того, коли ви натиснете Ctrl + C, ви можете:
    • Вийдіть з циклу negate-forever, вийміть помилку з subциклу, намагаючись приєднати число до рядка, а потім перейдіть до інтерпретації /// так, ніби ви закінчили заміщення рядка з себе нескінченну кількість разів.
    • Залиште subна півдорозі та продовжуйте інтерпретувати вираз із напіврядкою ///.
    • Вийдіть з інтерпретатора і поверніть неоцінену /// програму в REPL (хоча не STDOUT).

Приклад використання:

   f=:(0&$`((2{.{:@>&.>)((j{.]),-i@=`p@.~:~/@[,]}.~#@p+j=.0{p I.@E.])i 5;@}.&,'/';"0;&.>)@.(2<#)@}.[4:1!:2~{:@>@p=.>@{.@[)@((0;(0,:~1 0,.2);'\';&<1 0)<;._1@;:'/'&,)i=. ::](^:_)
   f 'no'
no
   f '/ world! world!/Hello,/ world! world! world!'
Hello, world!
   f '/foo/Hello, world!//B\/\\R/foo/B/\R'
Hello, world!
   f '//'  NB. empty string

   f '/\\/good/\/'
good

Ого. Я б назвав це мазохістським. +1
seequ

Коли я запускаю це, я отримую порожню рядок з кожного тестового випадку. Я використовую jqt64, що ви використовуєте для запуску цього?
bcsb1001

@ bcsb1001 Я використовував (64-розрядний) двійковий файл jconsole безпосередньо. Перевіряючи jqt зараз, я отримую фактично результати, за винятком /\\/good/\/тестового випадку; налагодження повідомляє мені про те, в чому полягає моє використання 1!:2&4, оскільки у jqt немає stdin / out. Буде розслідувати. Які ваші 9!:12''і 9!:14''?
алгоритм

@algorithmshark Моє 9!:12''6, і 9!:14''j701 / 2011-01-10 / 11: 25.
bcsb1001

4

Perl - 190

$|=1;$/=undef;$_=<>;while($_){($d,$_)=/(.)(.*)/;eval(!$e&&({'/','$a++','\\','$e=1'}->{$d})||('print$d','$b.=$d','$c.=$d')[$a].';$e=0');if($a==3){while($b?s/\Q$b/$c/:s/^/$c/){}$a=0;$b=$c=''}}

Прочитає ///програму від stdin до EOF.


Чи може підхід по лінії - m/^(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*)$/sвідповідати результатам, схемі та заміні все одночасно - зробити для коротшого гольфу? Я сам не знаю жодного Perl.
алгоритм

Я вважаю, що це не вдається/a/\0/a
Асона Тухід

3

Піп , 100 102 байти

Я ніколи не доводив, що Піп є повним Тьюрінгом (хоча це очевидно так), і замість того, щоб їхати звичайним маршрутом BF, я думав, що /// буде цікавим. Після того, як у мене було рішення, я зрозумів, що буду гольфу, і розміщу його тут.

101 байт коду, +1 для -rпрапора:

i:gJnf:{a:xW#i&'/NE YPOia.:yQ'\?POiya}W#iI'\Q YPOiOPOiEIyQ'/{p:VfY0s:VfIyQ'/WpNi&YviR:Xp{++y?ps}}E Oy

Ось моя версія з невмілими кохами з великими коментарями:

; Use the -r flag to read the /// program from stdin
; Stdin is read into g as a list of lines; join them on newline and assign to c for code
c : gJn

; Loop while c is nonempty
W #c {
 ; Pop the first character of c and yank into y
 Y POc
 ; If y equals "\"
 I yQ'\
  ; Pop c again and output
  O POc
 ; Else if y equals "/"
 EI yQ'/ {
  ; Build up pattern p from empty string
  p : ""
  ; Pop c, yank into y, loop while that is not equal to "/" and c is nonempty
  W #c & '/ NE Y POc {
   ; If y equals "\"
   I yQ'\
    ; Pop c again and add that character to p
    p .: POc
   ; Else, add y to p
   E p .: y
  }

  ; Yank 0 so we can reliably tell whether the /// construct was completed or not
  Y0
  ; Build up substitution s from empty string
  s : ""
  ; Pop c, yank into y, loop while that is not equal to "/" and c is nonempty
  W #c & '/ NE Y POc {
   ; If y equals "\"
   I yQ'\
    ; Pop c again and add that character to s
    s .: POc
   ; Else, add y to s
   E s .: y
  }

  ; If the last value yanked was "/", then we have a complete substitution
  ; If not, the code must have run out; skip this branch, and then the outer loop
  ; will terminate
  I yQ'/ {
   ; While pattern is found in code:
   W pNc {
    ; Set flag so only one replacement gets done
    i : 0
    ; Convert p to a regex; replace it using a callback function: if ++i is 1,
    ; replace with s; otherwise, leave unchanged
    c R: Xp {++i=1 ? s p}
   }
  }
 }
 ; Else, output y
 E Oy
}

Спробуйте в Інтернеті! (Зверніть увагу, що TIO не дає жодного результату, коли програма не припиняється, а також має обмеження часу. Для великих прикладів та нескінченних циклів рекомендується запускати Pip з командного рядка.)


Я думаю, це має бути pip + -r, 101 байт
Асона Тухід

3

C ++: Visual C ++ 2013 = 423, g ++ 4,9,0 = 442

Це ніколи не виграє, але оскільки я вирішив, що всі мої майбутні програмні проекти будуть написані на цій дивовижній мові, мені потрібен був перекладач для цього, і я подумав, що міг би поділитися тим, що я зробив ...

Різниця в балах полягає в тому, що Visual C ++ не потребує першого включення, але g ++. Оцінка передбачає, що закінчення рядків рахуються як 1.

#include<string.h>
#include<string>
#define M(x)memset(x,0,99);
#define P o[i])
#define N(x)P;else if(n<x)(P==92?
#define O (o[++i]):(P==47?n++:
#define S std::string
int main(int n,char**m){S o=m[1];char p[99],*q=p,r[99],*s=r;M(p)M(r)for(int i=0,t;i<=o.size();++i){if(!N(3)putchar O putchar(N(4)*q++=O(*q++=N(5)*s++=O(*s++=P;if(n>4){for(;;){if((t=o.find(p,i+1))==S::npos)break;o=o.substr(0,t)+r+o.substr(t+strlen(p));}M(p)M(r)n=2;q=p;s=r;}}}

1
Чи можете ви переписати if(!o[i]);, if(Pщоб зберегти символи, чи я не розумію, як працює #define?
Алгоритм

@algorithmshark як я це пропустив ?! якщо (! P ідеально. Я його зміню.
Джеррі Єремія

Кожен екземпляр Pin mainмає після нього пробіл, тож ви можете зберегти символ, замінивши їх пробілами крапками з комою та видаливши його #define. Потім, якщо ви можете використовувати #defines всередині інших, ви можете зберегти ще кілька, переписавши N(x)як (92==Pзамість того ж o[i]==92і Oтак само.
Алгоритм

@algorithmshark ви, очевидно, набагато кращі в цьому, ніж я. Дякую за допомогу.
Джеррі Єремія

Я знаю, що це близько чотирьох років, але перезапис N(x)як P;else if(n<x)(P==92?і зміна дзвінків Nвідповідно може заощадити кілька байт.
Zacharý

2

Python 2 (236), Python 3 (198?)

from __future__ import print_function
def d(i):
 t=0;p=['']*3+[1]
 while i:
  if'/'==i[0]:t+=1
  else:
   if'\\'==i[0]:i=i[1:]
   p[t]+=i[0]
  i=i[1:]
  print(end=p[0]);p[0]=''
  if t>2:
   while p[1]in i:i=i.replace(*p[1:])
   d(i);i=0

Називається як d(r"""/foo/Hello, world!//B\/\\R/foo/B/\R"""). Потрійні лапки потрібні лише в тому випадку, якщо ///програма містить нові рядки: інакше прості цитати в порядку.

EDIT: Цей перекладач тепер друкує матеріали, як очікувалося (раніше він друкувався лише в самому кінці, пор. Коментарі). Для Python 3 видаліть перший рядок (але у мене немає старої програми Python 3, тому не можу бути впевненим, що немає інших змін).


перекладач нічого не друкує до завершення проблематично. написання нескінченного циклу в /// можливо, тому ваш інтерпретатор не працює у програмах, що не закінчують, але все-таки друкують.
гордий haskeller

Виправлено @proudhaskeller.
Бруно Ле Флох

Насправді це не виправлено, він нічого не друкує /a/ab/bbaa/abb.
Бета-розпад

@BetaDecay /a/ab/bbaa/abbзастрягне в нескінченному циклі, не надрукуючи нічого, тому що перша заміна - a=> ab. Правильно a/ab/bbaa/abbпрацює, як рекламується.
алгоритм

@BetaDecay: окрім змін, запропонованих алгоритмом, вам може знадобитися включити параметр командного рядка, -uщоб змусити вихідний буфер розблокувати.
Бруно Ле Флох

2

Кобра - 226

sig Z as String
def f(l='')
    m=Z(do=[l[:1],l=l[1:]][0])
    n as Z=do
        if'/'<>(a=m())>'',return if(a=='\\',m(),a)+n()
        else,return''
    print n()stop
    p,s=n(),n()
    if''<l
        while p in l,l=l[:l.indexOf(p)+1]+s+l[p.length:]
        .f(l)


1

Python 2/3 (211 байт)

Наступний код, заснований на відповіді Бруно Ле Флоха, сумісний із Python 2 та Python 3.

Більше того, будучи ітеративним, а не рекурсивним, це не ризикує вразити максимальну глибину рекурсії Python.

def S(c):
 while c:
  B=["","",1]
  for m in 0,1,2:
   while c:
    if"/"==c[0]:c=c[1:];break
    if"\\"==c[0]:c=c[1:]
    if m:B[m-1]+=c[0]
    else:yield c[0]
    c=c[1:]
  while c and B[0]in c:c=c.replace(*B)

Привіт і ласкаво просимо до PPCG. Ви можете in(0,1,2)грати в гольф до in 0,1,2і [""]*2+[1]до ["","",1], в результаті чого виходить 211 байт .
Джонатан Фрех

Я пов’язав із зазначеною відповіддю і додав слово "байти". Якщо ви не згодні з моєю редакцією, не соромтесь відкотити.
Джонатан Фрех

Дякую Джонатане, ваші пропозиції дуже вітаються!
Карлос Луна,

0

BaCon , 391 387 395 байт

Зі вкладів на цій сторінці я працював лише програмою Python. Інші працюють для деяких /// зразків, або взагалі не працюють. Тому я вирішив додати свою версію, яка є реалізацією в BASIC.

Змагатися в конкурсі CodeGolf з BASIC непросто, оскільки BASIC використовує довгі слова як заяви. Єдина абревіатура, яка зазвичай зустрічається в BASIC, - це "?" знак, що означає PRINT.

Тож програма нижче може ніколи не виграти, але принаймні вона працює з усім демонстраційним кодом на цій сторінці Codegolf та на Вікі Esolangs . Включаючи всі версії "99 пляшок пива".

p$=""
r$=""
INPUT i$
WHILE LEN(i$)
t$=LEFT$(i$,1)
i$=MID$(i$,2)
IF NOT(e) THEN
IF t$="\\" THEN
e=1
CONTINUE
ELIF t$="/" THEN
o=IIF(o<2,o+1,0)
IF o>0 THEN CONTINUE
FI
FI
IF o=1 THEN
p$=p$&t$
ELIF o=2 THEN
r$=r$&t$
ELIF o=0 THEN
IF LEN(p$) THEN i$=REPLACE$(i$,p$,r$)
IF NOT(INSTR(t$&i$,"/")) THEN
?t$;
BREAK
ELSE
?LEFT$(i$,INSTR(i$,"/")-1);
i$=MID$(i$,INSTR(i$,"/"))
FI
p$=""
r$=""
FI
e=0
WEND
?i$

Додано оператор INPUT, щоб отримати вхід від користувача.
Пітер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.