Pierwszym językiem programowania, na który byłem narażony, był Sinclair BASIC . Podobnie jak wiele dialektów BASIC, wymaga numerowania wszystkich linii kodu źródłowego .
W rezultacie użycie GO TO
polecenia było idiomatyczne i powoduje wykonanie skoku do podanego numeru linii (bez etykiet).
Istnieje również pokrewne GO SUB
polecenie, które może być użyte jako podstawowe wywołanie funkcji. Ponownie wykonanie przeskakuje do podanego numeru wiersza, ale po osiągnięciu RETURN
polecenia wykonanie powraca do następnej instrukcji po GO SUB
.
Podobnie RUN
polecenie zrestartuje wykonanie programu w danym wierszu.
Każdy, kto spędził czas w tłumaczu BASIC o numerze wiersza, nauczy się korzystać ze schematu numeracji z przerwami. Dzieje się tak, aby łatwiej wstawiać nowe wiersze kodu. Jednak nawet wtedy nadal może być konieczne wstawienie nowych linii między kolejnymi numerami linii.
Biorąc pod uwagę numer BASIC o numerze wiersza jako dane wejściowe, wypisuje ten sam program, ale przenumerowany tak, że numery linii zaczynają się od 10 i są zwiększane o krok 10. Liczba wejść może mieć GO TO
lub GO SUB
polecenia, więc liczby z nimi związane również muszą zostać dostosowane.
GO TO
aGO SUB
polecenia są albo w osobnych wierszach, albo na ich końcuIF
THEN
. Można powiedzieć, że^(\d+) .*GO (TO|SUB) (\d+)$
wystarczy dopasować takie linie. Te polecenia w cudzysłowie należy zignorować.RUN
polecenia będą zawsze na swoich liniach. W takim przypadku numer linii jest opcjonalny. Jeśli go brakuje, tłumacz zaczyna po prostu na górze programu.Jeśli polecenie
GO TO
,GO SUB
lubRUN
odwołuje się do nieistniejącej linii, przeskakuje do następnej zdefiniowanej linii. Twój wpis musi sobie z tym poradzić i upewnić się, że wszelkie odniesienia do linii są stałe, aby wskazywały prawidłową linię. Zachowanie może być niezdefiniowane, jeśli w jednym z tych poleceń podany jest numer linii po zakończeniu programu.Numery linii zawsze będą dodatnimi liczbami całkowitymi od 1 do 9999 (zgodnie z instrukcją). Oznacza to, że programy wejściowe nigdy nie będą miały więcej niż 999 linii.
Linie wejściowe będą zawsze numerowane w kolejności rosnącej liczbowo.
Na potrzeby tego wyzwania zestawienia wejściowe będą zawierały tylko ASCII do wydruku. Nie musisz się martwić o zestaw znaków ZX. Mimo, że jeśli wejście jest faktycznie napisane w BASIC ZX lub właściwego montażu Z80 / kod maszynowy (i istnieją emulatory odchodzący istnieje ), a następnie można wybrać za Twój wkład mają być zakodowane w zestawie znaków ZX zamiast.
Nie możesz używać żadnych bibliotek lub programów numeracyjnych specjalnie dostosowanych do tego celu.
Przykładowe dane wejściowe:
1 REM "A rearranged guessing game"
2 INPUT A: CLS
3 INPUT "Guess the number ", B
10 IF A=B THEN PRINT "Correct": STOP
100 IF A<B THEN GO SUB 125
120 IF A>B THEN GO SUB 122
121 GO TO 3
125 PRINT "Try again"
126 RETURN
127 REM "An example of GO TO 7 and GO SUB 13 in quotes"
Przykładowe dane wyjściowe:
10 REM "A rearranged guessing game"
20 INPUT A: CLS
30 INPUT "Guess the number ", B
40 IF A=B THEN PRINT "Correct": STOP
50 IF A<B THEN GO SUB 80
60 IF A>B THEN GO SUB 80
70 GO TO 30
80 PRINT "Try again"
90 RETURN
100 REM "An example of GO TO 7 and GO SUB 13 in quotes"
Chciałem połączyć się z instrukcją obsługi ZX BASIC. Najlepsze, co mogłem znaleźć, to http://www.worldofspectrum.org/ZXBasicManual/index.html, ale wydaje się, że jest to martwy link. Maszyna powrotna ma jednak kopię .
GOTO 100 + A*10
, a dodatek C do ZX Spectrum Manual wymieniaGO TO
jako akceptację wyrażenia liczbowego (bez ograniczenia do stałych). Oto omówienie zalet obliczeńGOTO
na ZX80 i ZX81. BTW, nie mam pojęcia, dlaczego przestrzeń została dodana w wersji Spectrum.Odpowiedzi:
JavaScript (ES6) 177
Edytuj Dodano (kosztowne) skanowanie następnego ważnego numeru linii
TEST
źródło
Perl 6,
147145144142 bajtówPrawdopodobnie można to nieco pograć w golfa.
Rozszerzony
źródło
.min
. użyj{min %line-map.keys».Num.grep:*>=$1
zamiast tegoVisual Basic for Applications, 288 bajtów
Nie mogłem się oprzeć podaniu rozwiązania w dialekcie BASIC. Prawdopodobnie działa z Visual Basic 6 / .NET lub innymi nowoczesnymi wariantami z niewielkimi zmianami.
Dla zwięzłości użyłem wielu literowych zmiennych. Ponadto stłumiłem wszystkie niepotrzebne białe znaki (VBE automatycznie je rozszerza podczas importu). Liczba bajtów dotyczy końcowego pliku .BAS, z CHR (10) jako znakiem nowej linii.
Podprogram, który można wywołać z bezpośredniego okna VBE, otwiera program Sinclair BASIC (pierwszym parametrem jest ścieżka do pliku ASCII - z CHR (10) jako nową linią - zawierającą program), przenumeruje linie i zapisze wyniki w zmiennej Variant (drugi parametr).
Pomysł jest iteracyjne na wszystkich możliwych numerów linii source porządku rosnącym, a dla każdego z nich należy wymienić naraz wszystkich liczb dopasowanie linii, jak również
GO TO
,GO SUB
iRUN
odniesień do następnej dostępnej linii numer docelowy. Korzystając z tego podejścia, nie potrzebujemy żadnego rodzaju tabeli tłumaczeń. Numer linii docelowej jest zwiększany za każdym razem, gdy zostanie znalezione dopasowanie w numerze linii źródłowej, więc „błędne” odniesienia do linii są automatycznie dostosowywane do następnej poprawnej liczby. Znaki nowej linii są używane jako znaczniki początku i końca linii, a CHR (0) - nigdy nie używany w programie, ponieważ nie można go wydrukować - jest używany jako znacznik tymczasowy, aby uniknąć wielokrotnego numerowania tej samej linii.Kilka uwag:
Dla zwięzłości używamy mniejszego możliwego ciągu w celu dopasowania do skaczących instrukcji. Używając końca wiersza w naszych ciągach wyszukiwania, nie ryzykujemy dołączenia cytowanych zdarzeń lub funkcji użytkownika (które zawsze używają nawiasów w Sinclair).
GO TO
wymaga większego ciągu ze względu naFOR ... TO
konstrukcję (np. porównaj50 FOR X=AGO TO 100
i50 GO TO 100
)Kod nie obsługuje instrukcji w formie
GO TO200
(bez białych znaków), chociaż instrukcja ZX sugeruje, że jest poprawnym kodem na kilku przykładach (zajęłoby to kilkanaście więcej bajtów, aby sobie z tym poradzić).Kod dodaje nowy wiersz na początku, a drugi na końcu programu. Mogę to wyczyścić na końcu (kilkanaście kolejnych bajtów), ale sądzę, że ZX prawdopodobnie zignoruje puste linie.
Poniżej, bardziej czytelna wersja:
źródło
Pip
-rn
, 63 bajtyWypróbuj online!
Wyjaśnienie
Ustawiać
-r
Flag czyta wszystkie stdin i zapisuje go jako lista linii w zmiennej lokalnejg
. Zmienna globalnat
jest wstępnie zainicjalizowana na 10, a zmienna globalnas
jest wstępnie zainicjalizowana" "
.Wyciąga listę linii
g
do zmiennej globalnejy
, aby była dostępna w funkcji, którą zamierzamy zdefiniować.Funkcja tłumaczenia numeru wiersza
Konstruujemy funkcję, która mapuje z dowolnego numeru linii w oryginalnym schemacie numeracji (w tym nieistniejącym) na odpowiedni numer linii w nowym schemacie numeracji.
Załóżmy, że mamy następujące linie:
Chcemy zmapować 1 do 10, 2-4 do 20 i 5-9 do 30. Jeśli mamy listę oryginalnych numerów linii (
[1; 4; 9]
), możemy użyć operacji filtrowania, aby dowiedzieć się, ile z tych liczb jest mniej niż numer linii, którą próbujemy przekonwertować. Pomnóż ten wynik przez 10 i dodaj 10, a my mamy pożądaną odpowiedź.Na przykład podczas konwersji 9 występują dwie liczby linii (1 i 4) mniejsze niż 9. 2 * 10 + 10 daje 30. Podczas konwersji 3 liczba linii (1) jest mniejsza niż 3. 1 * 10 + 10 daje 20.
Oto kod (nieco zmodyfikowany, aby był łatwiejszy do odczytania):
Pierwsza wymiana:
GO TO
,GO SUB
, iRUN
Reszta programu jest pojedynczym wyrażeniem, które pobiera
g
i wykonuje kilka zamienników wyrażeń regularnych (które wektoryzują, odnosząc się do każdej liniig
).Oto pierwszy zamiennik:
Wyrażenie regularne pasuje do dowolnego z
RUN
,GO SUB
aGO TO
po nim następuje liczba, a następnie koniec linii. Zapewnia to, że nie pasuje do ciągów, ani nie pasujeRUN
bez numeru linii.Kolejność grup przechwytywania jest ważna. Pierwsza grupa rejestruje polecenia (jeden
RUN
,GO SUB
, ORGO TO
). Druga grupa, jeśli są stosowane, to rejestruje alboSUB
alboTO
. Nie musimy przechwytywać tej części, ale grupa nie przechwytująca wymagałaby dodatkowych bajtów. Następnie trzecia grupa przechwytuje numer linii.Do zamiany używamy funkcji zwrotnej. Dzięki funkcji zwrotnych w Pip, cały mecz jest pierwszym argumentem
a
, a grupy przechwytywania w kolejności są kolejne argumentyb
,c
,d
, ie
. Mamy więc polecenie w pierwszej grupie, która wchodzib
, i numer linii w trzeciej grupie, która wchodzid
. Jedyną zmianą musimy zrobić to przekazać numer wiersza przez naszą funkcję konwersji, który jest nazywany Lisp-style:(nd)
. Następnie łączymy to razem zb
spacją i zwracamy .Druga zamiana: numery linii
Wszystko, co pozostało do konwersji, to numery linii na początku linii.
Wyrażenie regularne dopasowuje ciąg cyfr na początku wiersza. Ponownie używamy funkcji zwrotnej; tym razem
n
wystarczy sama funkcja konwersji , ponieważ całe dopasowanie (pierwszy argumenta
) to liczba, którą chcemy przekonwertować.Ponieważ jest to ostatnie wyrażenie w programie, Pip automatycznie drukuje wynik.
-n
Flag oddziela listę wyników z nowej linii.źródło