Języki programowania na przestrzeni lat


167

W tym wyzwaniu użytkownicy wykonują kolejno trzy dość proste zadania kodowania w językach programowania, które mogą być stopniowo starsze.

Pierwsza odpowiedź musi korzystać z języka programowania, który został utworzony w 2015 roku. Gdy jest co najmniej jedna odpowiedź z języka 2015, odpowiedzi mogą używać języków programowania, które zostały utworzone w 2014 roku. Podobnie, odpowiedzi, które używają języków z 2013 roku są niedozwolone dopóki nie będzie co najmniej jednej odpowiedzi z 2014 r.

Zasadniczo użycie języka programowania z roku Y jest niedozwolone, dopóki nie zostanie złożona odpowiedź w języku z roku Y + 1. Jedynym wyjątkiem jest Y = 2015.

Znalezienie roku swojego języka

Aby odpowiedzieć na to pytanie, musisz znać rok, w którym Twój język programowania został „wyprodukowany”. Jest to oczywiście pojęcie subiektywne; niektóre języki były rozwijane przez wiele lat, a wiele języków wciąż jest aktualizowanych każdego roku. Niech rokiem, w którym dany język został „wyprodukowany”, będzie pierwszy rok, w którym implementacja tego języka pojawiła się w opinii publicznej.

Na przykład Python został „wyprodukowany” w 1991 r. , Choć jego rozwój trwał od 1989 r., A wersja 1.0 została wydana dopiero w 1994 r.

Jeśli ten rok jest nadal subiektywny, użyj zdrowego rozsądku, aby wybrać najbardziej odpowiedni rok. Nie daj się wciągnąć w lekkie nieporozumienia dotyczące rocznych wyborów. Podaj link do źródła, które mówi, kiedy powstał Twój język.

Różne wersje lub standardy języka programowania (np. Python 1, 2, 3) są liczone jako ten sam język z tym samym początkowym rokiem.

Tak więc, chyba że rokiem Twojego języka jest rok 2015, możesz przesłać odpowiedź dopiero po przesłaniu odpowiedzi, której rokiem jest rok tuż przed twoim.

Jeśli istnieje już prawidłowa odpowiedź z tego samego roku co twój, możesz odpowiedzieć. Nie ma znaczenia, czy Twój język został opracowany wcześniej czy później w tym roku.

Zadania

Musisz wykonać zadania od 1 do 3. Zadanie 0 jest opcjonalne.

Zadania te zostały mniej więcej wybrane tak, aby odpowiadały trzem ważnym aspektom programowania: dostarczaniu danych wyjściowych (Zadanie 1), zapętlaniu (Zadanie 2) i rekurencji (Zadanie 3).

Zadanie 0 - Historia języka (opcjonalnie)

Napisz co najmniej akapit wyjaśniający historię wybranego języka programowania: kto go opracował, dlaczego, jak itp. Jest to szczególnie zalecane, jeśli osobiście byłeś w pobliżu, kiedy powstał język, a może nawet odegrałeś rolę w jego rozwoju. Zapraszam do relacjonowania osobistych anegdot na temat wpływu, jaki język wywarł na ciebie lub twoją pracę, czy coś w tym rodzaju.

Jeśli jesteś zbyt młody, aby wiedzieć dużo o historii Twojego języka bez wielu badań, zastanów się nad pozostawieniem notatki starszym użytkownikom, która mówi, że mogą edytować Twój post i dodać trochę historii z pierwszej ręki.

Zadanie 1 - „Witaj, świecie!” Wariant

Napisz program, który drukuje

[language name] was made in [year made]!

do standardowego obszaru wyjściowego twojego języka (standardowe dla najnowszych języków).

Na przykład, jeśli językiem byłby Python, wynikiem byłoby:

Python was made in 1991!

Zadanie 2 - ASCII art

Napisz program, który pozwala użytkownikowi wprowadzić nieparzystą liczbę całkowitą dodatnią (możesz założyć, że dane wejściowe są zawsze poprawne) i wydrukuje literę N ASCII wykonaną za pomocą znaku N.

Jeśli wejście to 1, wyjście to:

N

Jeśli wejście wynosi 3, wyjście to:

N N
NNN
N N

Jeśli wejście wynosi 5, wyjście to:

N   N
NN  N
N N N
N  NN
N   N

Jeśli wejście wynosi 7, wyjście to:

N     N
NN    N
N N   N
N  N  N
N   N N
N    NN
N     N

Wzór trwa w ten sposób. Dane wyjściowe mogą zawierać końcowe spacje.

Zadanie 3 - GCD

Napisz program, który pozwala użytkownikowi wprowadzić dwie liczby całkowite dodatnie (możesz założyć, że dane wejściowe są zawsze prawidłowe) i wypisuje ich największy wspólny dzielnik . Jest to definiowane jako największa dodatnia liczba całkowita, która dzieli obie liczby bez pozostawiania reszty. Można go łatwo obliczyć za pomocą algorytmu euklidesowego .

Przykłady:

8, 124
12, 84
3, 303
5689, 21
234, 8766

Możesz użyć wbudowanej funkcji, ale spróbuj dowiedzieć się, czy była ona dostępna w pierwszej wersji Twojego języka. Jeśli nie, spróbuj go nie używać.

Zasady

  • Możesz odpowiedzieć wiele razy, ale każda nowa odpowiedź musi używać języka utworzonego co najmniej 5 lat przed językiem w Twojej ostatniej odpowiedzi. Jeśli więc odpowiedziałeś językiem 2015, nie możesz odpowiedzieć ponownie, dopóki 2010 nie będą dozwolone. Jeśli zaczniesz od odpowiedzi z 2010 r., Nie możesz uczynić odpowiedzi z 2015 r. Drugą odpowiedzią, ponieważ rok 2015 nie jest wcześniejszy niż 2010.
  • Jeśli to możliwe, napisz swój kod, aby działał w pierwszej wersji Twojego języka (lub tak starej, jak to możliwe). (Nie jest to wymagane, ponieważ znalezienie starych kompilatorów / tłumaczy dla niektórych języków może być trudne.)
  • Powstrzymaj się od opublikowania języka, który został już opublikowany, chyba że na opublikowanej odpowiedzi są znaczące błędy lub masz zupełnie inny sposób wykonywania zadań.
  • Gra w golfa jest w porządku, ale nie jest wymagana.
  • Końcowy znak nowej linii w wynikach dowolnego programu jest w porządku.
  • W przypadku zadań 2 i 3 wszystkie wartości wejściowe poniżej pewnego rozsądnego maksimum, takie jak 2 16, powinny działać (co najmniej 256).
  • Twój język musiał istnieć przed opublikowaniem tego pytania.
  • Bardzo stare języki programowania mogą mieć różne formy danych wejściowych i wyjściowych niż te, o których dziś myślimy. To jest w porządku. Wykonuj zadania najlepiej jak potrafisz w kontekście swojego języka.

Punktacja

Wynik Twojego zgłoszenia to:

upvotes - downvotes + (2015 - languageYear) / 2 

W związku z tym do liczby głosów przed każdym rokiem 2015 dodaje się 0,5, co daje przewagę starszym językom. Zgłoszenie z najwyższym wynikiem wygrywa.

Lista odpowiedzi

Poniższy fragment kodu zawiera listę wszystkich poprawnych odpowiedzi według ich roku językowego.

Musisz rozpocząć swój post od tej linii Markdown , aby upewnić się, że jest poprawnie wymieniony:

#[year] - [language name]

Na przykład:

#1991 - Python

Nazwa języka może znajdować się w linku (będzie to ten sam link na liście odpowiedzi):

#1991 - [Python](https://www.python.org/)

Odpowiedzi, które nie są zgodne z tym formatem lub mają rok, który nie jest jeszcze dozwolony, lub pochodzą od użytkownika, który odpowiedział już w ciągu ostatnich 5 lat, są oznaczone jako nieprawidłowe.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script>$(function(){function e(e,r){var a="https://api.stackexchange.com/2.2/questions/48476/answers?page="+e.toString()+"&pagesize=100&order=asc&sort=creation&site=codegolf&filter=!YOKGPOBC5Yad160RQxGLP0r4rL";$.get(a,r)}function r(e){if(e.items.forEach(function(e){var r=e.link,a=e.owner.display_name,i=e.body.match(/<h1\b[^>]*>(\d{4}) - (.*?)<\/h1>/);if(i&&i.length>=3)var h=parseInt(i[1]),u=i[2];h&&u&&n>=h&&h>=t&&(!d.hasOwnProperty(e.owner.user_id)||d[e.owner.user_id]-h>=p)?(d[e.owner.user_id]=h,h==t&&--t,o.hasOwnProperty(h)||(o[h]=[]),o[h].push({language:u,user:a,link:r,score:e.score+(n-h)/2})):s.push(' <a href="'+r+'">'+a+"</a>")}),e.has_more)runQuery(++a,r);else{for(var i=n,h=[];o.hasOwnProperty(i);){for(var u=$("<tr>").append($("<td>").text(i.toString())),l=$("<td>"),c=$("<td>"),g=$("<td>"),f=0;f<o[i].length;f++){var v=o[i][f];l.append(v.language),c.append($("<a>").html(v.user).attr("href",v.link)),g.append(v.score),f+1<o[i].length&&(l.append("<br><br>"),c.append("<br><br>"),g.append("<br><br>"))}u.append(l).append(c).append(g),h.push(u),--i}$("#answers").find("tbody").append(h),s.length>0?$("#invalid").append(s):$("#invalid").remove()}}var a=1,n=2015,t=n-1,p=5,o={},s=[],d={};e(1,r)})</script><style>html *{font-family: Helvetica, Arial, sans-serif;}table{border: 4px solid #a4a; border-collapse: collapse;}th{background-color: #a4a; color: white; padding: 8px;}td{border: 1px solid #a4a; padding: 8px;}div{font-size: 75%;}</style><table id='answers'> <tr> <th>Year</th> <th>Language</th> <th>User (answer link)</th> <th>Score</th> </tr></table><div id='invalid'><br>Invalid Answers:</div>


2
To powinno pomóc.
świst

20
Wikipedia ma listę wszystkiego: dla języków innych niż ezoteryczne z roku na rok.
Sanchises

2
Czy Zadanie 3 powinno faktycznie używać rekurencji, czy wystarczy, aby przyniosło poprawny wynik? Jeśli muszę napisać własną funkcję GCD, zwykle po prostu używam pętli, ale napisałem rekursywną specjalnie dla tego wyzwania. Istnieje wiele przesłanych odpowiedzi, które wykorzystują tylko pętlę.
CJ Dennis

5
Mam ochotę zrobić drugie konto tylko po to, żeby nas wyprzedzić po 1971 roku.
marinus

5
Jeśli uda nam się go przywrócić do 1952 r., Mam kogoś, kto rozpala historyczną maszynę, która może zrobić rozwiązania z 1951 r. (Pegasus) i przetestować je!
Brian Tompsett - 汤 莱恩

Odpowiedzi:


172

2013 - Dogescript

Dogescript to język stworzony w 2013 roku przez Zach Bruggemana. Jest niczym innym jak zamiennikiem składni dla Javascript, aby czytał jak wewnętrzne monologi memetycznego Shiba Inusa.

Witaj doze

console dose loge with "Dogescript was made in 2013!"

ASCII Art

such N much N
          much i as 0 next i smaller N next i more 1
              very doge is ("N" + " ".repeat(N-2) + "N").split('')
              s[i] is "N";
              console dose loge with doge.join('')
                              wow
                                      wow

GCD

such gcd_doge much doge, dooge
    rly dooge
              gcd_doge(dooge, doge % dooge)
  but
    rly doge smaller 0
           -doge
    but
          doge
  wow
        wow

112
Wow, takie +1. Bardzo odpowiedz Dużo jakości.
Alex A.

27
Dołączyłem do codegolfa, aby głosować na tę odpowiedź!
Derek Tomes,

21
Nie mogę nawet odczytać GCD z prostą twarzą
Cole Johnson,

16
Nie mogę odczytać gcd_doge jako good_dog. Pomoc
Yann,

Fantastyczny. Jednak zgodnie z LANGUAGE.md podwójne cudzysłowy nie są obsługiwane. Chciałbym też wyjaśnić to s[i]trochę!
Docteur

66

2015 - Retina

Retina jest językiem programowania opartym na wyrażeniach regularnych, który napisałem, aby móc konkurować w wyzwaniach PPCG z odpowiedziami zawierającymi tylko wyrażenia regularne, bez zbędnego narzutu wywołania wyrażenia regularnego w jakimś języku hosta. Siatkówka jest kompletna w Turinga. Aby to udowodnić, zaimplementowałem 2-tagowy solver systemowy, a także Regułę 110 . Jest napisany w języku C #, dlatego obsługuje zarówno smak .NET (domyślnie), jak i smak ECMAScript (poprzez flagę).

Siatkówka może działać w wielu trybach, ale najbardziej odpowiedni dla obliczeń (i Turing-kompletny) to tryb Zamień. W trybie Zastąp dajesz Retinie parzystą liczbę plików źródłowych. Są one następnie sparowane, pierwsza z każdej pary jest wyrażeniem regularnym, a druga zamiennikiem. Są one następnie wykonywane w kolejności, manipulując wprowadzaniem krok po kroku. Wyrażenie regularne może być również poprzedzone konfiguracją (oddzieloną znakiem` ). Najważniejszą opcją (która sprawia, że ​​Retina jest kompletna) jest to +, że Retina stosuje zamianę w pętli, aż wynik przestanie się zmieniać. W poniższych przykładach również używam ;, co tłumi dane wyjściowe na etapach pośrednich.

W każdym z poniższych zgłoszeń każdy wiersz znajduje się w osobnym pliku źródłowym. (Alternatywnie możesz użyć nowego-s opcji i umieścić wszystkie linie w jednym pliku.) Puste pliki / linie są reprezentowane jako <empty>. Pliki / linie zawierające pojedynczą spację są reprezentowane jako <space>.

Wyjaśnienia są dość długie, więc przeniosłem je na koniec postu.

Programy

"Witaj świecie!" Wariant

<empty>
Retina was made in 2015!

ASCII Art N

Zakłada się, że STDIN jest zakończony nową linią.

;`^
#
;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#
;`#
<empty>
;`\d
N
;`.(?<=(?=(.*\n)).*)|\n
$1
;`N(?=N\n.*\n.*\n`$)
<space>
;+`N(?=.?(.)+\n.* (?<-1>.)+(?(1)!)\n)
<space>
;`(?<=^.*\n.*\nN)N
S
;+`(?<=\n(?(1)!)(?<-1>.)+S.*\n(.)+N?)N
S
S
<space>

GCD

Wymaga to, aby STDIN nie był zakończony znakiem nowej linii.

;`\b(?=\d)
#
;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#
;`#
<empty>
;`\d
1
;`^(.+)\1* \1+$
$1
;`$
#:0123456789
;+`^(?=1)(1*)\1{9}(#(?=.*(0))|1#(?=.*(?<3>1))|11#(?=.*(?<3>2))|111#(?=.*(?<3>3))|1111#(?=.*(?<3>4))|11111#(?=.*(?<3>5))|111111#(?=.*(?<3>6))|1111111#(?=.*(?<3>7))|11111111#(?=.*(?<3>8))|111111111#(?=.*(?<3>9)))
$1#$3
#|:.*
<empty>

Objaśnienia

"Witaj świecie!" Wariant

To jest dość trywialne. Nie pobiera danych wejściowych (tzn. Pusty ciąg znaków), niczego nie dopasowuje i zamienia na Retina was made in 2015!. Można również sprawić, aby działał dla dowolnych danych wejściowych, zastępując [\s\S]*na przykład wzorzec . Spowodowałoby to slurpowanie STDIN i zastąpienie go całym wyjściem.

ASCII Art N

To ma dość wiele etapów. Chodzi o to, aby przekonwertować dane wejściowe na jednoargumentowe, utworzyć blok N x N Ns, a następnie „wykroić” dwa trójkąty. Przejdźmy przez poszczególne etapy. Pamiętaj, że ;jedynie tłumi wyjścia pośrednie, ale +powoduje, że zamiana jest stosowana w pętli.

;`^
#

Proste: dodaj a #do wejścia. Zostanie on użyty jako znacznik w konwersji do jednostkowej.

;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#

To zamienia jedną cyfrę na unarną. Pobiera przekonwertowane cyfry (\d*)i powtarza je 10 razy. A następnie pobiera następną cyfrę i dołącza odpowiednią liczbę cyfr. Rzeczywista wartość cyfr nie ma znaczenia na tym etapie. Kiedy #osiągnie koniec liczby, wyrażenie regularne już nie pasuje, a konwersja jest zakończona. Na przykład numer 127będzie przetwarzany jako

#127
1#27
111111111122#7
1111111111221111111111221111111111221111111111221111111111221111111111221111111111221111111111221111111111221111111111227777777#

gdzie ostatni wiersz zawiera dokładnie 127 cyfr.

;`#
<empty>
;`\d
N

Dwa proste etapy, które się tego pozbywają, #a następnie przekształcają wszystkie cyfry N. Poniżej wykorzystam dane wejściowe 7jako przykład. Więc teraz mamy

NNNNNNN

Następny etap

;`.(?<=(?=(.*\n)).*)|\n
$1

zamienia każdy Nz nich na cały ciąg (pamiętaj, że zawiera on końcowy znak nowej linii), a także usuwa sam końcowy znak nowej linii. W ten sposób pojedynczy wiersz zamienia się w kwadratową siatkę:

NNNNNNN
NNNNNNN   
NNNNNNN
NNNNNNN
NNNNNNN
NNNNNNN
NNNNNNN

Teraz górny trójkąt. Po pierwsze, zaczynamy od obrócenia litery N w prawym dolnym rogu w spację:

;`N(?=N\n.*\n.*\n`$)
<space>

Lookahead zapewnia, że ​​modyfikujemy poprawne N. To daje

NNNNNNN
NNNNNNN   
NNNNNNN
NNNNNNN
NNNNN N
NNNNNNN
NNNNNNN

I teraz

;+`N(?=.?(.)+\n.* (?<-1>.)+(?(1)!)\n)
<space>

jest wyrażeniem regularnym, które pasuje do znaku Npowyżej lub w lewym górnym rogu znaku spacji i zastępuje go spacją. Ponieważ zamiana się powtarza, jest to zasadniczo wypełnienie zalewowe, które zamienia trzecią liczbę z początkowej przestrzeni na więcej przestrzeni:

N     N
NN    N   
NNN   N
NNNN  N
NNNNN N
NNNNNNN
NNNNNNN

Na koniec powtarzamy to samo z dolnym trójkątem, ale używamy innej postaci, więc już istniejące spacje nie powodują nieprawidłowego wypełnienia zalewowego:

;`(?<=^.*\n.*\nN)N
S

ustawia ziarno:

N     N
NN    N   
NSN   N
NNNN  N
NNNNN N
NNNNNNN
NNNNNNN

Następnie

;+`(?<=\n(?(1)!)(?<-1>.)+S.*\n(.)+N?)N
S

wypełnia powódź.

N     N
NN    N   
NSN   N
NSSN  N
NSSSN N
NSSSSNN
NSSSSSN

I w końcu

S
<space>

Zamienia je Sw spacje i gotowe:

N     N
NN    N   
N N   N
N  N  N
N   N N
N    NN
N     N

GCD

GCD w unary jest w rzeczywistości bardzo trywialny z wyrażeniem regularnym. Większość z nich składa się z konwersji dziesiętnej na jednostkową i jednostkowej na dziesiętną. Można to zrobić bardziej kompaktowo, ale to nie jest golf golfowy, więc ...

;`\b(?=\d)
#
;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#
;`#
<empty>
;`\d
1

Etapy te są zasadniczo takie same jak powyżej, z tym wyjątkiem, że obie liczby wejściowe są konwertowane, a wynik używa 1s zamiast Ns (nie ma to znaczenia). Więc jeśli dane wejściowe 18 24byłyby, to by to wytworzyło

111111111111111111 111111111111111111111111

Teraz

;`^(.+)\1* \1+$
$1

jest całym obliczeniem GCD. Dopasowujemy wspólny dzielnik, przechwytując liczbę 1s, a następnie stosując odwołania wsteczne, aby zapewnić, że obie liczby można zapisać, powtarzając ten ciąg (i nic więcej). Ze względu na to, jak działa backtracking w silniku wyrażeń regularnych (tj. .+Jest chciwy), zawsze da to największe wspólnego dzielnika. Ponieważ dopasowanie obejmuje cały ciąg, po prostu odpisujemy pierwszą grupę przechwytującą, aby uzyskać nasz GCD.

Wreszcie konwersja jednostkowa na dziesiętną ...

;`$
#:0123456789

Dołącz znacznik #, separator :i wszystkie cyfry do ciągu. Jest to konieczne, ponieważ nie można warunkowo wytwarzać nowych znaków w zastępstwie wyrażeń regularnych. Jeśli chcesz warunkowej zamiany, musisz wyciągnąć znaki z samego łańcucha, więc umieszczamy je tam.

;+`^(?=1)(1*)\1{9}(#(?=.*(0))|1#(?=.*(?<3>1))|11#(?=.*(?<3>2))|111#(?=.*(?<3>3))|1111#(?=.*(?<3>4))|11111#(?=.*(?<3>5))|111111#(?=.*(?<3>6))|1111111#(?=.*(?<3>7))|11111111#(?=.*(?<3>8))|111111111#(?=.*(?<3>9)))
$1#$3

Jest to odwrotność wcześniejszego jednoznacznego rozszerzenia. Znajdujemy największą wielokrotność 10, która pasuje do bieżącego ciągu. Następnie wybieramy kolejną cyfrę na podstawie reszty i dzielimy wielokrotność przez 10, przesuwając jednocześnie znacznik.

#|:.*
<empty>

I na koniec po prostu krok czyszczenia, aby pozbyć się znacznika, separatora i cyfr pomocnika.


Myślę, że powinieneś dodać instrukcję, aby przekonwertować dane liczbowe na ciąg jednoargumentowy i instrukcję, aby przekonwertować ciąg jednoargumentowy z powrotem na dane liczbowe. Konwersja z czystym wyrażeniem regularnym jest fajna, ale zdecydowanie zbyt niezręczna.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳

8
+1 Byłem całkiem pewien, że zgłoszenie w 2015 roku będzie językiem dla CodeGolf.
Zero Fibre

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ Zastanawiałem się nad tym wcześniej. Myślę, że w przypadku większości golfów kodowych prawdopodobnie po prostu wezmę wkład Unary (chyba że wyzwanie wyraźnie określa „dziesiętny” lub coś w tym rodzaju ...). Myślałem o zrobieniu tego samego, ale nie jest to golf golfowy i chciałem pokazać, że mogę również obsługiwać dziesiętne dane wejściowe i wyjściowe.
Martin Ender

6
Wspaniała robota. Siatkówka jest naprawdę fajna. Nawiasem mówiąc, fajnie jest też zobaczyć diament obok twojego imienia! :)
Alex A.,

Zabawne, że chociaż w tych zawodach preferowane są stare języki, ten najmłodszy wciąż wygrywa =)
Claudiu

60

2013 - Snap !

Snap ! jest językiem opartym na Scratch , opracowanym na Uniwersytecie Berkeley. Jest to aktualizacja do Scratch zawierająca najwyższej klasy dane i niestandardowe bloki (funkcje). Podobnie jak Scratch, nie jest oparty na tekście, ale raczej oparty na wizualnych „blokach”, które łączą się ze sobą.

Snap ! , napisany w JavaScript, jest następcą BYOB, który został napisany w Squeak Smalltalk. Snap ! został wydany w wersji beta do użytku publicznego w marcu 2013 r .

Snap ! w rzeczywistości nie jest językiem ezoterycznym. Jest używany jako język programowania dla Beauty and Joy of Computing (BJC) kursu AP CS w Berkeley i innych.

Pomagałem w testowaniu i tym podobnych.

Wariant „Hello World”

ASCII Art „N”

enter image description here

Używa stdlib dla niektórych bloków.

Całkiem proste zapętlenie tutaj. Pobiera dane wejściowe. Następnie po prostu dodajemy to wszystko razem i mówimy (wynik dla n = 5):

enter image description here

Wykorzystałem tu wolność, aby użyć 2 spacji zamiast 1, ponieważ Snap! nie mówi nic w monospace.

GCD

Algorytm euklidesowy nie jest bardzo szybki, ale działa i jest dość prosty. (Przepraszam, napisałem literówkę w nazwie bloku. Teraz zamknąłem kartę bez zapisywania. Po prostu będę musiał pozostać.)

enter image description here

Ta definicja funkcji wygeneruje następnie ten blok:

enter image description here


3
To wygląda jak programowanie w Alice ...
mbomb007

4
To właśnie otrzymujesz w przypadku języków blokowych. Do rzeczy, wiele języków wygląda podobnie. ;)
Scimonster

1
Nawet Scratch ma funkcję mod, więc zakładam, że możesz przyspieszyć działanie GCM / GCD z blokiem opartym na if (b == 0), a następnie innym GCM (b, a% b)
Alchymist

55

2007 - LOLKOD

Historia języka

LOLCODE został stworzony w 2007 roku przez Adama Lindsaya, badacza z Lancaster University. Jego składnia oparta jest na memach Lolcats spopularyzowanych przez Cheezburger, Inc.

"Witaj świecie!" Wariant

HAI
VISIBLE "LOLCODE wuz maed in 2007!"
KTHXBYE

ASCII Art N

HAI

BTW, read n from stdin
GIMMEH n

BTW, convert n from YARN to NUMBR
n R PRODUKT OF n AN 1

BOTH SAEM n AN 1, O RLY?
    YA RLY
        VISIBLE "N"
    NO WAI
        VISIBLE "N"!

        I HAS A butt ITZ 1
        IM IN YR toilet UPPIN YR butt TIL BOTH SAEM butt AN DIFF OF n AN 1
            VISIBLE " "!
        IM OUTTA YR toilet

        VISIBLE "N"

        I HAS A kat ITZ 2
        IM IN YR closet UPPIN YR kat TIL BOTH SAEM kat AN n
            VISIBLE "N"!
            BOTH SAEM kat AN 2, O RLY?
                YA RLY
                    VISIBLE "N"!
                NO WAI
                    I HAS A doge ITZ 1
                    IM IN YR l00p UPPIN YR doge TIL BOTH SAEM doge AN DIFF OF kat AN 1
                        VISIBLE " "!
                    IM OUTTA YR l00p
                    VISIBLE "N"!
            OIC

            I HAS A brd ITZ 1
            IM IN YR haus UPPIN YR brd TIL BOTH SAEM brd AN DIFF OF n AN kat
                VISIBLE " "!
            IM OUTTA YR haus

            VISIBLE "N"
        IM OUTTA YR closet

        VISIBLE "N"!

        I HAS A d00d ITZ 1
        IM IN YR lap UPPIN YR d00d TIL BOTH SAEM d00d AN DIFF OF n AN 1
            VISIBLE " "!
        IM OUTTA YR lap

        VISIBLE "N"
OIC

KTHXBYE

Wartości są odczytywane jako ciągi (YARN) ze standardowego wejścia GIMMEH . Można je przekonwertować na liczbę (NUMBR), mnożąc przez 1.

Wartości są drukowane do standardowego przy użyciu VISIBLE . Domyślnie dodawany jest nowy wiersz, ale można go wyłączyć, dodając wykrzyknik.

GCD

HAI

GIMMEH a
a R PRODUKT OF a AN 1

GIMMEH b
b R PRODUKT OF b AN 1

I HAS A d00d ITZ 1
IM IN YR food UPPIN YR d00d TIL BOTH SAEM b AN 0
    I HAS A kitty ITZ a
    I HAS A doge ITZ b
    a R doge
    b R MOD OF kitty AN doge
IM OUTTA YR food

VISIBLE SMOOSH "gcd is " a

KTHXBYE

SMOOSH wykonuje konkatenację ciągów.


13
Wreszcie język, który każdy może zrozumieć.
ASCIIThenANSI

26
IM IN YR toilet UPPIN YR buttŁadne nazwy zmiennych
Cole Johnson,

13
@ColeJohnson: Zawsze staram się wybierać nazwy zmiennych, które mają sens w sytuacji, zamiast x1, x2itp
Alex A.

2
Wesoły. Nie powinienem tego czytać w pracy.
Alan Hoover

@AlanHoover: Oczywiście Lolz są ważniejsze niż Jobz.
Alex A.

43

1982 - PostScript

PostScript to język do tworzenia grafiki wektorowej i drukowania.

Firma Adobe została założona w 1982 r., A ich pierwszym produktem był PostScript. Język był używany w drukarkach: polecenia są interpretowane przez drukarkę w celu utworzenia obrazu rastrowego, który jest następnie drukowany na stronie. Był to bardzo powszechny element drukarek laserowych już w latach 90. Ale drukarka jest oczywiście dość obciążona procesorem, a ponieważ procesory komputerowe stały się bardziej wydajne, sensowniejsze było rasteryzowanie na komputerze niż w drukarce. PostScript w dużej mierze odszedł od drukarek konsumenckich, chociaż nadal istnieje na wielu bardziej zaawansowanych drukarkach.

Standard, który zastąpił PostScript, to mało znany format o nazwie PDF.

Kiedy zacząłem programować, PostScript wypadł z mody, ale nauczyłem się trochę, gdy byłem na uniwersytecie, jako inny sposób tworzenia dokumentów dla TeX-a. Różniło się to od innych języków programowania, których użyłem (odwrotna notacja, stos, drukowanie na stronie zamiast konsoli), ale fajnie było odkurzyć ten stary język dla zabawy.

Ponieważ PostScript jest językiem drukowania, bardziej odpowiednie wydaje się użycie go do wydrukowania czegoś, a następnie wysłania danych wyjściowych do konsoli.

Zadanie 1

/Courier findfont
12 scalefont
setfont
newpath

100 370 moveto
(PostScript was made in 1982!\n) show

Pierwsze kilka linii tworzyło płótno do rysowania. Następnie movetopolecenie każe PS rysować w określonej pozycji, ishow drukuje ciąg na stronie. Zauważ, że nawiasy oznaczają ciąg znaków w PostScript, a nie cudzysłowy.

Zadanie 2

/asciiartN {% stack: N row col
            % output: draws an "ASCII art" N

  % PostScript doesn't allow you to pass variables directly into a function;
  % instead, you have to pass variables via the global stack. Pop the variables
  % off the stack and define them locally.
  6 dict begin
  /row exch def
  /col exch def
  /N exch def

  % Define how much space will be between each individual "N"
  /spacing 15 def

  % Get the width of the "N". We need this to know where to draw the right-hand
  % vertical
  /endcol col spacing N 1 sub mul add def

  % One row is drawn at a time, with the bottom row drawn first, and working
  % upwards. This stack variable tracks which column the diagonal is in, and so
  % we start on the right and work leftward
  /diagcol endcol def

  % Repeat N times: draw one row at a time
  N {
    % Left-hand vertical of the "N"
    col row moveto
    (N) show

    % Right-hand vertical of the "N"
    endcol row moveto
    (N) show

    % Diagonal bar of the "N"
    diagcol row moveto
    (N) show

    % Advance to the next row. This means moving the row one space up, and the
    % diagonal position one place to the left.
    /row row spacing add def
    /diagcol diagcol spacing sub def

  } repeat

  end
} def

1 100 200 asciiartN
3 150 200 asciiartN
5 230 200 asciiartN

Napisałem funkcję do rysowania „ASCII art” N, ale funkcje PostScript nie mogą przyjąć argumentu. Zamiast tego wypychasz argumenty na stos, a następnie je odsuwasz. To jest/x exch def linia.

Przykład: załóżmy, że stos 8 9 2. Najpierw wypychamy nazwę /xna stos, więc stos jest 8 9 2 /x. exchOperatora zamienia dwie wartości stos, tak teraz stos jest 8 9 /x 2. Następnie defwyświetla dwie górne wartości stosu i określa, /xże ma wartość 2. Stos jest teraz 8 9.

Kiedy zacząłem używać PostScript, uznałem to za nieco mylące. Przeczytałem o stosie jako koncepcji teoretycznej, ale po raz pierwszy użyłem go w praktyce.

Reszta funkcji to kod rysunkowy: zacznij od prawego dolnego rogu, wypełniając wiersz od lewej do prawej po przekątnej.

Zadanie 3

/modulo {% stack: x y
         % output: returns (x mod y)
  3 dict begin
  /y exch def
  /x exch def

  % If x = y then (x mod y) == 0
  x y eq {0} {

    % If x < y then (x mod y) == x
    x y lt {x} {

      % If x > y then subtract floor(x/y) * y from x
      /ycount x y div truncate def
      /x x ycount y mul sub def

      /x x cvi def
      x

    } ifelse
  } ifelse
} def

/gcd {% stack: a b
      % returns the gcd of a and b
  2 dict begin
  /b exch def
  /a exch def

  % I'm using the recursive version of the Euclidean algorithm

  % If b = 0 then return a
  b 0 eq {a} {

    % Otherwise return gcd(b, a mod b)
    /a a b modulo def
    b a gcd
  } ifelse

} def

/displaygcd {% stack: a b xcoord ycoord
             % displays gcd(a,b) at position (xcoord, ycoord)
  5 dict begin
  /ycoord exch def
  /xcoord exch def
  /b exch def
  /a exch def
  /result a b gcd def

  xcoord ycoord moveto
  result 20 string cvs show

  % end
} def

8 12 100 80 displaygcd
12 8 150 80 displaygcd
3 30 200 80 displaygcd
5689 2 250 80 displaygcd
234 876 300 80 displaygcd

Ponownie użyłem formy algorytmu Euclid, ale zapomniałem, że PostScript ma wbudowany operator modulo, więc musiałem napisać własny. Okazało się to przydatnym przypomnieniem ograniczeń programowania stosowego. Moja pierwsza implementacja modulobyła oparta na rekursji:

modulo(x, y)
    if (x = y) return 0
    elif (x < y) return x
    else return module(x - y, y)

co jest w porządku, dopóki nie spróbujesz uruchomić tego, gdy xjest duży i yjest mały (np. 5689 i 2). Możesz mieć tylko do 250 elementów na stosie, więc znacznie przekraczałem limit stosu. Ups Musiałem tam wrócić do deski kreślarskiej.

Sam kod GCD jest dość prosty. Ale podobnie jak funkcje nie mogą przyjmować argumentów, więc nie mają zwracanych wartości. Zamiast tego musisz przesunąć wynik na stos, gdzie ktoś inny może go później wyrzucić. Właśnie to aib a gcd linie zrobić: kiedy skończysz oceny, będą forsować wartość na stosie.

Jeśli umieścisz cały kod w dokumencie i wydrukujesz go, będzie wyglądać wynik:

enter image description here


8
Haha Uwielbiam fotografię wydrukowanego kawałka papieru. Wydaje się odpowiedni na 1982 r.
Alex A.

1
Dziękujemy również za opisanie sposobu, w jaki otrzymano (dosłowne) przepełnienie stosu - teraz rozumiem bardziej intuicyjnie, dlaczego języki mają maksymalną głębokość rekurencji.
DLosc

2
@AlexA .: Tak, ale wydruk z matrycą punktową (z otworami po bokach papieru) byłby jeszcze bardziej odpowiedni . ;-)
Amos M. Carpenter

@ AmosM.Carpenter: nie bardzo, nie sądzę, aby jakakolwiek drukarka igłowa kiedykolwiek obsługiwała PostScript. Zawsze był bardzo związany z drukarkami laserowymi.
ninjalj

41

2009 - > <>

Zainspirowany przez Befunge,> <> (Fish) to ezoteryczny język 2D oparty na stosie, tzn. Przepływ programu może być w górę, w dół, w lewo lub w prawo. Początkowa wersja> <> zawierała wielowątkowość gdzie [i] stworzony i zakończył wątki, ale dla uproszczenia Powody te instrukcje zostały zmienione w celu tworzenia i usuwania nowych stosów odpowiednio.

Aktualny oficjalny tłumacz dla> <> można znaleźć tutaj . Niestety link do starego interpretera na wiki Esolang jest zepsuty.

"Witaj świecie!" Wariant

"!9002 ni edam saw ><>"l?!;obb+0.

Zwróć uwagę, jak ciąg jest zapisywany wstecz -> <> technicznie nie ma ciągów, a jedynym typem danych jest dziwna mieszanka char, int i float. "przełącza parsowanie ciągów, wypychając każdy znak na stos, aż do "spełnienia zamknięcia .

Druga połowa kodu przesuwa następnie długość stosu l, sprawdza, czy wynosi zero, ?!a jeśli tak, to program się kończy ;. W przeciwnym razie wskaźnik instrukcji będzie kontynuował, wysyłając górną część stosu oprzed wykonaniem bb+0., co teleportuje wskaźnik do pozycji (22, 0)tuż przedl , tworząc pętlę.

ASCII Art N

&0 > :&:&:*=?;  :&:&%  :0=?v  :&:&1-=?v  :{:{-&:&,{=?v   " " o   \

                           > ~"N"o                           v    
   +                                  > ~"N"oao              v    
   1                                                 >"N"o   v    

   \                                                         <   /

Z odstępami dla przejrzystości. Możesz to wypróbować w nowym tłumaczu online tutaj i zobaczyć, jak wskaźnik instrukcji porusza się w kółko - pamiętaj tylko, aby wpisać liczbę w polu tekstowym „Początkowy stos”. Jeśli korzystasz z interpretera języka Python, użyj -vflagi do zainicjowania stosu, np

py -3 fish.py ascii.fish -v 5

W przypadku tego programu wstawiamy dane wejściowe ndo rejestru za pomocą &i wciskamy 0, które będziemy wywoływać w icelu „iteracji”. Reszta programu to gigantyczna pętla, która wygląda następująco:

:&:&:*=?;          If i == n*n, halt. Otherwise ...
:&:&%              Push i%n
:0=?v              If i%n == 0 ...
>~"N"o               Print "N"
:&:&1-=?v          Else if i%n == n-1 ...
>~"N"oao             Print "N" and a newline
:{:{-&:&,{=?v      Else if i%n == i//n, where // is integer division...
>~"N"o               Print "N"
" "o               Otherwise, print a space
1+                 Increment i

Następnie powtarzamy pętlę od początku.

Strzałki ^>v<zmieniają kierunek przebiegu programu, a lustra /\odzwierciedlają kierunek przebiegu programu.

GCD

>:{:}%\
;n{v?:/
v~@/

Oto przykład, jak może wyglądać program w golfa> <>. Jeszcze raz możesz wypróbować to w tłumaczu online (wpisz dwie wartości oddzielone przecinkami w polu „Początkowy stos”, np. 111, 87) Lub używając -vflagi interpretera Python, np.

py -3 fish.py gcd.fish -v 111 87

Ten program wykorzystuje algorytm euklidesowy. Oto GIF, który przygotowałem wcześniej:

enter image description here

Zauważ, że> <> jest toroidalny, więc kiedy vwykonywana jest lewa dolna instrukcja, wskaźnik instrukcji opada w dół, owija się i pojawia się ponownie u góry.


Edycja: Sprawiając, że kod działa całkowicie od prawej do lewej , @randomra zdołał zgolić trzy bajty

<~@v!?:%}:{:
;n{/

Chyba nie grałem wystarczająco w golfa :)


27
I w ten sposób dowiedziałem się, że nazwa ><>to palindrom.
Zev Eisenberg,

33

2012 - Element

Jest to język, który wymyśliłem na początku 2012 roku jako prosty język golfa. Rozumiem przez to, że przeciążenie operatora jest bardzo małe lub wcale. Operatorzy są również prostsi i mają mniejszą liczbę niż większość współczesnych języków golfowych.

Najciekawszymi cechami tego języka są jego struktury danych. Istnieją dwa stosy i skrót, które służą do przechowywania informacji.

Stos m to główny stos, w którym mają miejsce operacje arytmetyczne i większość innych operacji. Kiedy dane są wprowadzane lub drukowane, to tam idzie lub jest pobierane.

Stos c to stos kontrolny. To tutaj zachodzi arytmetyka logiczna. Najwyższe wartości stosu c są używane przez pętle If i While jako warunek.

Hash jest miejscem, w którym przechowywane są zmienne. ;i~ przechowywania i pobierania danych z mieszania, odpowiednio.

Element jest językiem bardzo słabo wpisanym. Wykorzystuje zdolność Perla do swobodnego interpretowania liczb jako ciągów znaków i odwrotnie.

W tym momencie równie dobrze mogę dołączyć całą dokumentację dla tego języka. Można znaleźć oryginalne 2012 tłumacza, napisany w Perlu, prawo tutaj . Aktualizacja: Stworzyłem bardziej użyteczną wersję, którą możesz znaleźć tutaj .

OP    the operator.  Each operator is a single character
STACK tells what stacks are affected and how many are popped or pushed
      "o" stands for "other effect"
HASH  tells if it involves the hash
x & y represent two values that are already on the stack, so the effect of
      the operator can be more easily described

OP     STACK  HASH   DESCRIPTION
text     ->m         --whenever a bare word appears, it pushes that string onto 
                       the main stack
_       o->m         --inputs a word and pushes onto main stack
`       m->o         --output.  pops from main stack and prints
xy;    mm->    yes   --variable assignment.  the top stack element y is assigned 
                       the value x
~       m->m   yes   --variable retrieval.  pops from main stack, pushes contents 
                       of the element with that name
x?      m->c         --test. pops x and pushes 0 onto control stack if x is '0' or 
                       an empty string, else pushes 1
><=     m->c         --comparison. pops two numbers off of stack and performs 
                       test, pushes 1 onto control stack if true and 0 if false
'       m->c         --pops from main stack and pushes onto control stack
"       c->m         --pops from control stack and pushes onto main stack
&|     cc->c         --AND/OR. pops two items from control stack, performs and/or 
                       respectively, and pushes result back onto control stack
!       c->c         --NOT. pops a number off of control stack, pushes 1 if 0 or 
                       empty string, 0 otherwise
[]       c           --FOR statement (view the top number number from control stack 
                       and eval those many times)
{}       c           --WHILE (loop until top number on control stack is 0, also 
                       does not pop)
#       m->          --discard. pops from main stack and destroys
(       m->mm        --pops from main stack, removes first character, pushes the 
                       remaining string onto stack, and pushes the removed character 
                       onto stack
)       m->mm        --pops from main stack, removes last character, pushes the 
                       remaining string onto stack, and pushes the removed character 
                       onto stack
+-*/%^ mm->m         --arithmetic. pops two most recent items, adds/negates
                       /multiplies/divides/modulates/exponentiates them, and places 
                       the result on the stack 
xy@    mm->o         --move. pops x and y and moves xth thing in stack to move to 
                       place y in stack
x$      m->m         --length. pops x and pushs length of x onto the stack
xy:    mm->o         --duplication. pops x and y and pushes x onto the stack y times
xy.    mm->m         --concatination. pops x and y and pushes x concatonated with y
\        o           --escapes out of next character, so it isn't an operator and can
                       be pushed onto the stack
,      m->mm         --character conversion. pops from main stack, coverts it to char
                       and pushes, and converts to num and pushes
Newlines and spaces separate different elements to be pushed 
onto the stack individually, but can pushed onto the stack using \

Zadanie 1 - Wydrukuj tekst

Element\ was\ made\ in\ 2012\!`

Jedną z bardziej niezręcznych części języka jest brak ograniczników ciągów, dlatego w tym ciągu potrzebne są znaki specjalne. Na `końcu drukuje ciąg.

Zadanie 2 - ASCII art

_+'[y~1+y;0[1+4:"2:'=1=|y~=|\ [#N]`"#]\
`]

Tutaj będziesz świadkiem manipulacji stosami. Aby wyjaśnienie było trochę łatwiejsze do sformatowania, zastąpię nowy wiersz znakiem Li spacją znakiem S.

_+'[y~1+y;0[1+4:"2:'=1=|y~=|\S[#N]`"#]\L`]
_+'      input line, convert to #, move to c-stack
[        FOR loop
 y~1+y;  increment the y-pos
 0       set the x-pos (the top # on the stack) to zero
 [       FOR loop
  1+4:   increment x-pos and make 3 additional copies (4 is total #)
  "2:'   make a copy of the N size on the main stack
  =      if x-pos == size
  1=     or if x-pos == 1
  y~=|   of if x-pos == y-pos
  \S     (always) push a space
  [      the IF body (technically a FOR loop)
   #N    if true, remove the space and push an N
  ]      end IF
  `      output the pushed character
  "#     remove the result of the conditional
 ]       end x-pos FOR
 \L`     output a newline
]        end y-pos FOR

Po zrobieniu ekstremalnej gry w golfa tej odpowiedzi znalazłem 39-bajtowe rozwiązanie, chociaż jest znacznie bardziej skomplikowane.

_'1[y~+y;[#1+3:"2:'%2<y~=|\ [#N]`"]\
`]

Zadanie 3 - GCD

__'{"3:~2@%'}`

Jest to metoda oparta na stosie.

__                 input the two numbers
  '                use one of the number as a condition so the WHILE loop starts
   {        }      a WHILE loop. Repeats while the c-stack has a true value on top
    "              get the number back from the c-stack to do operations on it
     3:            make it so that there are threes copies on the stack
       ~           takes one of the copies from earlier and converts it to a zero
        2@         take the top item on the stack and move it behind the other two #s
          %        modulo operation
           '       use this number as the condition
             `     since one number is zero (and on the c-stack) print the 
                   other number, which is on m-stack

29

2012 - Julia

Historia języka

Julia została opracowana w 2012 roku przez Jeffa Bezansona, Stefana Karpińskiego i Virala Shaha, podczas gdy Jeff był studentem Massachussets Institute of Technology (MIT), pod kierunkiem profesora Alana Edelmana. Ich motywacją było pragnienie języka programowania, który byłby open source, szybki i dynamiczny (między innymi), przy jednoczesnym zachowaniu łatwości użycia w różnych aplikacjach. Produktem była Julia, świeże podejście do wysokowydajnych obliczeń naukowych.

"Witaj świecie!" Wariant

println("Julia was made in 2012!")

Drukowanie do STDOUT w Julii jest dość proste!

ASCII Art N

function asciin(n)
    # Create an nxn matrix of spaces
    m = fill(" ", (n, n))

    # Fill the first and last columns with "N"
    m[:,1] = m[:,n] = "N"

    # Fill the diagonal elements with "N"
    setindex!(m, "N", diagind(m))

    # Print each row of the matrix as a joined string
    for i = 1:n
        println(join(m[i,:]))
    end
end

Kod jest wcięty pod kątem czytelności, ale Julia nie nakłada żadnych ograniczeń na białe znaki.

GCD

function g(a, b)
    b == 0 ? a : g(b, a % b)
end

Ostatnia rzecz wymieniona w funkcji jest niejawnie zwracana.


27

1988 - Mathematica

A może powinienem to nazwać Wolfram Language ?

Zadanie 0

Twórcą Mathematica jest Stephen Wolfram, założyciel i dyrektor generalny Wolfram Research. Przed opracowaniem Mathematica był fizykiem. W fizyce było wiele obliczeń algebraicznych, więc został użytkownikiem Macsyma .

Wolfram uzyskał tytuł doktora w 1979 roku, kiedy miał 20 lat. Myślał, że potrzebuje lepszej CAS niż Macsyma do fizyki, więc zaczął pisać SMP („Program manipulacji symbolicznych”). Pierwsza wersja SMP została wydana w 1981 roku. SMP był poprzednikiem Mathematica. Chociaż miał on głęboki wpływ na Mathematica, żaden z jego kodów nigdy nie był używany w Mathematica.

W 1986 roku Wolfram postanowił napisać „ostateczny system obliczeniowy”. Zaczął pisać kod w 1986 r., A założył Wolfram Research w 1987 r. Ostatecznie Mathematica 1.0 została wydana 23 czerwca 1988 r.

Mathematica 1.0

Nie znalazłem Mathematica 1.0. W rzeczywistości Mathematica 1.0 nie miała wersji Windows ani Linux. Ale znalazłem Mathematica 2.0 na chińskiej stronie internetowej. Nadal można go uruchomić w systemie Windows XP.

Mathematica 2.0

Zadanie 1

Print["Mathematica was made in 1988!"]

Lub po prostu:

"Mathematica was made in 1988!"

Zadanie 2

W dzisiejszej Mathematica możemy napisać:

asciiArtN[n_] := Print @@@ SparseArray[{i_, 1 | i_ | n} -> "N", {n, n}, " "]

Podobnie jak Julia i R. , jest to rozwiązanie macierzowe. W Mathematica można zdefiniować rzadką macierz za pomocą dopasowania wzorca.

Jednak SparseArrayzostał wprowadzony w Mathematica 5.0, więc nie możemy go używać w Mathematica 1.0.

Oto rozwiązanie, które działa w Mathematica 1.0:

asciiArtN[n_] := Block[{f},
  f[i_, 1]  = "N";
  f[i_, i_] = "N";
  f[i_, n]  = "N";
  f[__]     = " ";
  Apply[Print, Array[f, {n, n}], 1];
]

Nie możemy pisać, f[i_, 1 | i_ | n] = "N"ponieważ Alternativeszostał wprowadzony w Mathematica 2.0.

Zadanie 3

Możemy po prostu użyć wbudowanej funkcji:

gcd = GCD

Lub możemy użyć definicji GCD:

gcd = Max[Intersection @@ Divisors[{##}]] &;

Lub możemy użyć LCM , chociaż częściej LCM jest obliczany z GCD:

gcd = Times[##]/LCM[##] &;

Lub możemy użyć algorytmu euklidesowego z dopasowaniem wzorca:

gcd[a_, 0] := a
gcd[a_, b_] := gcd[b, Mod[a, b]]

Lub jako funkcja anonimowa:

gcd = If[#2 == 0, #1, #0[#2, Mod[##]]] &;

Wszystkie powyższe funkcje zostały wprowadzone w Mathematica 1.0.


3
To jest znacznie lepsza odpowiedź niż moja. Usunę moje.
Martin Ender

25

1999 - XSLT

World Wide Web Consortium (W3C) utworzona XSLT do przekształcania danych XML do HTML, tekst, itp Poniższe przykłady zakładają wejście jest zamknięte w <input>..</input>znacznikach.

Zadanie 1

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="no"/>
  <xsl:template match="/input">XSLT was made in 1999!</xsl:template>
</xsl:stylesheet>

Ten jest prosty. Dopasowuje inputznacznik na najwyższym poziomie i zastępuje go pożądanym wyjściem.

Zadanie 2

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="no"/>
  <xsl:template match="/input">
    <xsl:call-template name="loop">
      <xsl:with-param name="i">1</xsl:with-param>
      <xsl:with-param name="n">
        <xsl:value-of select="."/>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>
  <xsl:template name="loop">
    <xsl:param name="i"/>
    <xsl:param name="n"/>
    <xsl:choose>
      <xsl:when test="$i = 1 or $i = $n">
        <xsl:text>N</xsl:text>
        <xsl:call-template name="spaces">
          <xsl:with-param name="n">
            <xsl:value-of select="$n - 2"/>
          </xsl:with-param>
        </xsl:call-template>
        <xsl:text>N&#13;&#10;</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>N</xsl:text>
        <xsl:call-template name="spaces">
          <xsl:with-param name="n">
            <xsl:value-of select="$i - 2"/>
          </xsl:with-param>
        </xsl:call-template>
        <xsl:text>N</xsl:text>
        <xsl:call-template name="spaces">
          <xsl:with-param name="n">
            <xsl:value-of select="$n - $i - 1"/>
          </xsl:with-param>
        </xsl:call-template>
        <xsl:text>N&#13;&#10;</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="$i &lt; $n">
      <xsl:call-template name="loop">
        <xsl:with-param name="i">
          <xsl:value-of select="$i + 1"/>
        </xsl:with-param>
        <xsl:with-param name="n">
          <xsl:value-of select="$n"/>
        </xsl:with-param>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
      <xsl:template name="spaces">
    <xsl:param name="n"/>
    <xsl:if test="$n &gt; 0">
      <xsl:text> </xsl:text>
      <xsl:call-template name="spaces">
        <xsl:with-param name="n">
          <xsl:value-of select="$n - 1"/>
        </xsl:with-param>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Ten definiuje 2 szablony rekurencyjne loopi spaces. loopz parametrami ii nwygeneruje pożądaną moc wyjściową n, zaczynając od pozycji i. spacesz parametrem nwygenerujen spacje.

Zadanie 3

Dane wejściowe muszą być w <input><num>..</num><num>..</num></input>tagach.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="no"/>
  <xsl:template match="/input">
    <xsl:call-template name="gcd">
      <xsl:with-param name="a"><xsl:value-of select="num[1]"/></xsl:with-param>
      <xsl:with-param name="b"><xsl:value-of select="num[2]"/></xsl:with-param>
    </xsl:call-template>
  </xsl:template>
  <xsl:template name="gcd">
    <xsl:param name="a"/>
    <xsl:param name="b"/>
    <xsl:choose>
      <xsl:when test="$b = 0"><xsl:value-of select="$a"/></xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="gcd">
          <xsl:with-param name="a"><xsl:value-of select="$b"/></xsl:with-param>
          <xsl:with-param name="b"><xsl:value-of select="$a mod $b"/></xsl:with-param>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Ten jest tylko szablonem rekurencyjnym, gcdktóry wykorzystuje algorytm euklidesowy.


I mówią, że INTERCAL jest dziwny!
kirbyfan64sos

2
@ kirbyfan64sos Aby być uczciwym, i tak nie należy go używać do tych rzeczy ...
LegionMammal978,

24

2014 - CJam

CJam został stworzony przez aditsu użytkownika PPCG i został wydany około kwietnia 2014 .

"Witaj świecie!" Wariant

"CJam was made in 2014!"

CJam automatycznie drukuje zawartość stosu na końcu programu

ASCII Art N

ri:R'#*a_R2-,{_)S*'#+\R((-zS*+}%+\+R<zN*

Objaśnienie kodu:

ri:R                                       "Read the input as integer in R";
    '#*a                                   "Get a string of R # and wrap it in an array";
        _R2-,{                }%           "Copy that string and then run this loop R-2";
                                           "times for the diagonal";
              _)S*                         "Get iteration index + 1 spaces";
                  '#+                      "Append the hash";
                     \R((-zS*+             "Append remaining spaces";
                                +\+        "Append and prepend the initial # string";
                                   R<      "Take only R columns/rows. This is for";
                                           "tackling input 1";
                                     zN*   "Transpose and join with new lines";

Pobiera wysokość / szerokość N jako dane wejściowe przez STDIN. Wypróbuj online tutaj

GCD

l~{_@\%}h;

Pobiera dwie liczby jako dane wejściowe za pośrednictwem STDIN. Wypróbuj online tutaj


Zdaję sobie sprawę, że to nie jest [code-golf], ale możesz skrócić program ASCII-art N do ri_S*0'NtW'Nta1$*\,Sf*'Nf+..e>N*współczesnego CJam.
Esolanging Fruit

24

1990 - Haskell

Haskell jest popularny (a raczej powinienem powiedzieć: najbardziej popularny) ?) Czystym językiem funkcjonalnym. Wyróżnia się z głównego nurtu dzięki nietypowemu modelowi oceny (domyślnie wszystko jest leniwe lub, technicznie rzecz biorąc, nie ścisłe) oraz systemowi opartemu na Hindley-Milner, który nawet teraz jest nadal jednym z najpotężniejszych na rynku.

Zadanie 1

main = putStrLn "Haskell was made in 1990!"

Zadanie 2

-- Infinite list of growing letters 'N'
bigNs :: [[[Char]]]
bigNs = ["N"]
      : ["NN","NN"]
      : [ ins (ins 'N' t) $ map (ins ' ') n | n@(t:_) <- tail bigNs ]

-- Insert a new element after the head (i.e. at the second position).
ins :: a -> [a] -> [a]
ins x (l:ls) = l:x:ls

Demo, wydrukuj całą nieskończoną listę (dopóki użytkownik nie przerwie lub świat się nie skończy ...)

GHCi> mapM_ (putStrLn . unlines) bigNs
N

NN
NN

N N
NNN
N N

N  N
NN N
N NN
N  N

N   N
NN  N
N N N
N  NN
N   N

N    N
NN   N
N N  N
N  N N
N   NN
N    N

...

Oczywiście możesz łatwo przejść do jednego z nich, uzyskując dostęp tylko do jednego elementu nieskończonej listy:

main :: IO ()
main = do
   i <- readLn
   putStrLn . unlines $ bigNs!!i

Zadanie 3

gcd' :: Integer -> Integer -> Integer
gcd' a 0 = a
gcd' a b = gcd' b $ a`mod`b

23

1972 - INTERCAL

I myślałeś, że Fortran i Cobol są dziwni. To szalone!

Zadanie 1

DO ,1 <- #27
DO ,1SUB#1 <- #110
DO ,1SUB#2 <- #32
DO ,1SUB#3 <- #72
PLEASE DO ,1SUB#4 <- #136
DO ,1SUB#5 <- #88
DO ,1SUB#6 <- #136
PLEASE DO ,1SUB#7 <- #64
DO ,1SUB#8 <- #80
DO ,1SUB#9 <- #46
PLEASE DO ,1SUB#10 <- #22
DO ,1SUB#11 <- #104
DO ,1SUB#12 <- #184
PLEASE DO ,1SUB#13 <- #202
DO ,1SUB#14 <- #78
DO ,1SUB#15 <- #48
PLEASE DO ,1SUB#16 <- #96
DO ,1SUB#17 <- #128
DO ,1SUB#18 <- #162
PLEASE DO ,1SUB#19 <- #110
DO ,1SUB#20 <- #32
DO ,1SUB#21 <- #114
PLEASE DO ,1SUB#22 <- #120
DO ,1SUB#23 <- #240
DO ,1SUB#24 <- #128
PLEASE DO ,1SUB#25 <- #208
DO ,1SUB#26 <- #200
DO ,1SUB#27 <- #52
DO READ OUT ,1
DO GIVE UP

Nie zamierzam wyjaśniać systemu wejścia i wyjścia INTERCAL; po prostu to przeczytaj i mam nadzieję, że nie umrzesz.

Zadanie 2

DO WRITE IN 7
DO .1 <- .7
DO .2 <- #1
PLEASE DO (1010) NEXT
DO .8 <- .3
DO .5 <- .7
DO .6 <- .8
DO ,9 <- #2

DO (100) NEXT
DO (1) NEXT

(100) DO (99) NEXT
DO ,9SUB#1 <- #142
DO ,9SUB#2 <- #114
PLEASE DO READ OUT ,9
DO ,9SUB#1 <- #176
DO ,9SUB#2 <- #80
PLEASE DO READ OUT ,9
PLEASE GIVE UP

(99) DO .1 <- .7
DO .2 <- #1
PLEASE DO (1010) NEXT
DO .1 <- '.3~.3'~#1
PLEASE DO FORGET .1
DO RESUME #1

(1) PLEASE DO (3) NEXT
PLEASE DO FORGET #1
DO (1) NEXT

(3) DO (4) NEXT
PLEASE GIVE UP

(4) DO (8) NEXT
DO ,9SUB#1 <- #176
DO ,9SUB#2 <- #80
PLEASE DO READ OUT ,9
DO .6 <- .8
DO .1 <- .5
DO .2 <- #1
DO (1010) NEXT
DO .5 <- .3
DO .1 <- '.5~.5'~#1
PLEASE DO FORGET .1
DO RESUME #1

(8) DO (5) NEXT

(5) PLEASE DO (6) NEXT
PLEASE DO FORGET #1
DO (5) NEXT

(6) PLEASE DO (7) NEXT
DO RESUME #2

(7) DO (10) NEXT
DO .1 <- .6
DO .2 <- #1
PLEASE DO (1010) NEXT
DO .6 <- .3
DO .1 <- '.6~.6'~#1
PLEASE DO FORGET .1
DO RESUME #1

(10) DO (11) NEXT
DO (13) NEXT
DO (14) NEXT
DO (15) NEXT

(11) DO (111) NEXT
DO (112) NEXT

(13) DO (113) NEXT
DO (112) NEXT

(14) DO (114) NEXT
DO (112) NEXT

(111) DO .1 <- .6
DO .2 <- .8
DO (1010) NEXT
DO .1 <- '.3~.3'~#1
PLEASE DO FORGET .1
DO RESUME #1

(112) DO ,9SUB#1 <- #142
DO ,9SUB#2 <- #114
PLEASE DO READ OUT ,9
DO RESUME #3

(113) DO .1 <- .6
DO .2 <- #1
DO (1000) NEXT
DO .1 <- .5
DO .2 <- .3
DO (1010) NEXT
DO .1 <- '.3~.3'~#1
PLEASE DO FORGET .1
DO RESUME #1

(114) DO .1 <- '.6~.6'~#1
PLEASE DO FORGET .1
DO RESUME #1

(15) DO ,9SUB#1 <- #252
DO ,9SUB#2 <- #4
PLEASE DO READ OUT ,9
DO RESUME #2

Dobroć łaskawa.Trochę mi to zajęło. Numery etykiet są bałaganem i dlatego odzwierciedlają to. Nie zamierzam tego wyjaśniać, chyba że ktoś zapyta.

Zadanie 3

DO WRITE IN .5
DO WRITE IN .6

DO (1) NEXT

(1) PLEASE DO (3) NEXT
DO FORGET #1
DO (1) NEXT

(3) DO (4) NEXT
DO READ OUT .5
PLEASE GIVE UP

(4) DO .1 <- .5
DO .2 <- .6
PLEASE DO (1040) NEXT
DO .1 <- .3
DO .2 <- .6
PLEASE DO (1039) NEXT
DO .2 <- .3
DO .1 <- .5
DO (1010) NEXT
DO .5 <- .6
DO .6 <- .3
DO .1 <- '.6~.6'~#1
PLEASE DO FORGET .1
DO RESUME #1

Ten jest odrobinę prostszy. Z powodu ... dziwności INTERCAL, musisz wprowadzić następujące liczby:

THREE FIVE

Na przykład, aby uzyskać GCD 42 i 16, wpisałbym:

FOUR TWO
ONE SIX

Drukuje również cyfry rzymskie ... ponieważ to jest INTERCAL dla ciebie!


2
Czy nie powinno to być 19 7 2? (Rozumiem, jeśli po napisaniu tego jesteś trochę oszołomiony: P) Twoja odpowiedź jest uważana za nieważną z powodu tego błędu, co byłoby wstydem.
marinus

@marinus Dziękujemy! Naprawiony!
kirbyfan64sos

5
PROSZĘ WYJAŚNIĆ. (Oczywiście, kiedy masz czas;)
DLosc

1
INTERCAL to mój ulubiony język, którego nigdy się nie nauczyłem!
CJ Dennis

1
PLEASE GIVE UP. Już to zrobiłem .-.
RedClover

23

1967 - APL

W 1957 r. Na Uniwersytecie Harvarda Ken Iverson zaczął opracowywać notację matematyczną do manipulacji tablicami. W latach 60. jego notacja została opracowana w języku programowania w IBM. Pierwsze częściowe wdrożenie zostało stworzone w 1963 r., A nawet zostało użyte w szkole średniej do nauczania uczniów o funkcjach transcendentalnych. Pełna, użyteczna implementacja musiała poczekać do 1965 r. Przez dwa lata była używana tylko wewnętrznie przez IBM. W 1967 r. IBM wydał publicznie interpreter APL działający na komputerze IBM 1130, który został ukończony w 1966 r. Możesz zrozumieć, jak trudno jest wybrać na niego rok, jednak myślę, że powinien to być rok 1967, ponieważ jest to pierwszy rok, pełne wdrożenie zostało udostępnione opinii publicznej. Jeśli ktoś naprawdę się nie zgadza, mógłbym to zmienić.

Kod źródłowy APL \ 360 jest dostępny online , podobnie jak emulator. Właśnie tego użyłem do przetestowania tych przykładów. Pochodzi z 1967 roku i wraz z APL \ 1130 (dla wspomnianego wyżej IBM 1130) jest mniej więcej prawdziwym oryginałem. Zgodnie z oczekiwaniami jest bardzo prymitywny. Brakuje wsparcia dla takich drobiazgów jak małe litery, każdy operator działa tylko z wbudowanymi funkcjami, a zestaw wbudowanych funkcji jest bardzo rzadki (w szczególności jest tylko or i robi nie podwaja się jak gcd). Oryginalny, pełny opis jest dostępny tutaj , jednak zauważyłem, że wersja, którą posiadam, nie jest nawet kompletna w odniesieniu do tego dokumentu, brakuje między innymi.

Udostępniłem programy zarówno w formacie Unicode (abyś mógł je odczytać), jak i w oryginalnym kodowaniu (abyś mógł je wyciąć i wkleić w oknie APL emulatora).

Niewiarygodnie, programy te działają poprawnie bez żadnych zmian (oprócz kodowania) we współczesnych wersjach Dyalog, NARS2000 i GNU APL. Myślę, że znalazłem sposób na napisanie przenośnej APL: udawaj, że to 1967!

Zadanie 1:

Unicode:

⎕←'APL WAS MADE IN 1967!'

APL \ 360:

L[Kapl was made in 1967ÝK

Zadanie 2:

Unicode:

⎕←' N'[1+((2⍴N)⍴(⍳N)∊1,N)∨(⍳N)∘.=⍳N←⎕]

APL \ 360:

L[K nK;1-::2Rn"R:In"E1,n"(:In"J.%In[L'

Zadanie 3:

Rozwiązałem to w standardowy sposób rekurencyjny. Teoretycznie możesz zrobić coś sprytnego i zorientowanego na tablicę, na przykład odpowiedź J; w praktyce jednak wykorzystuje ono pamięć O (N) i szybko przytłacza sprzęt i oprogramowanie z ery Flower-Power.

Unicode:

∇R←A GCD B
R←A
→(B=0)/0
R←B GCD B|A
∇

⎕←⎕ GCD ⎕

APL \ 360:

Gr[a gcd b
r[a
{:b%0"/0
r[b gcd bMa
G

L[L gcd L

To jest niesamowite.
Alex A.

22

1996 - Ocaml

Czekałem ponad dzień, aby ktoś wypełnił 1996, żebym mógł wypełnić Ruby. Dlaczego więc nie nauczyć się OCaml, wydaje się podobny do haskell ...

Witaj świecie

print_endline "OCaml was made in 1996!";;

ASCII

let ascii n =
  let rec ascii' = function
    | 0 -> ()
    | i ->
        let s = "N" ^ String.make (n-2) ' ' ^ "N" in
        String.fill s (n-i) 1 'N';
        print_endline s;
        ascii' (i-1)
  in ascii' n;;

Zmienne struny!

GCD

let rec gcd a b = if b = 0 then a else gcd b (a mod b);;

Nie ==i infix mod, to urocze


Przepraszam, wypełniłem Ruby :)
Zero Fibre

4
+1 za naukę języka, aby odpowiedzieć na to wyzwanie. :)
Alex A.

Właśnie nauczyłeś się F #! (to OCaml na CLR plus kilka dodatków).
Robert Fraser

22

2005 - Preludium

Prelude jest językiem bardzo zabawne, którego kod źródłowy składa się z kilku „głosy”, które są wykonywane równolegle, a które ja naprawdę cieszyć rozwiązywania problemów . Ma to być reprezentacja ASCII jego siostrzanego języka Fuga , który faktycznie bierze pliki .midi jako kod źródłowy i koduje instrukcje znalezione w Preludium jako interwały w melodiach głosów.

Preludium jest dość minimalistyczne, a Turing zakończone (pod warunkiem, że używasz co najmniej 2 głosów). Jak powiedziałem, głosy (wiersze kodu) są wykonywane jednocześnie, kolumna po kolumnie. Każdy głos działa na swoim własnym stosie, który jest inicjowany do nieskończonej liczby zer. Prelude obsługuje następujące instrukcje:

0-9 ... Push the corresponding digit.
+   ... Add the top two numbers on the stack.
-   ... Subtract the top number from the one beneath.
#   ... Discard the top of the stack.
^   ... Copy the top value from the voice above.
v   ... Copy the top value from the voice below.
?   ... Read a number and push it onto the stack.
!   ... Print the top number (and pop it from the stack).
(   ... If the top of the stack is zero, jump past the matching ')'.
)   ... If the top of the stack is zero, jump to the column after the matching '('.

Kilka dodatkowych uwag:

  • Głosy są cykliczne, więc ^na górze głosu kopiuje się z głosu na dole (i odwrotnie).
  • Wiele ?i !w tej samej kolumnie są wykonywane od góry do dołu.
  • Zgodnie ze specyfikacją języka , ?i! odczytu i zapisu znaków z odpowiednim kodem charakter. Jednak interpreter Pythona ma również przełącznik w kodzie, aby zamiast tego drukować same liczby. Do celów testowych faktycznie używam zmodyfikowanej wersji, która może również odczytywać liczby zamiast znaków. Ale wokół panuje zgoda, że numeryczne dane wejściowe / wyjściowe mogą być faktycznie podawane jako wartości bajtów, dlatego te modyfikacje nie są konieczne do stworzenia prawidłowych programów zajmujących się liczbami.
  • Dopasowane (i )nie muszą być w tym samym głosie. Głos używany w tym stanie jest zawsze tym, w którym (pojawia się. Stąd położenie pionowe nie )ma żadnego znaczenia.
  • Ze względu na charakter jednoczesnego wykonywania Preludium, każda instrukcja w tej samej kolumnie co a (jest wykonywana tylko raz przed uruchomieniem pętli i niezależnie od tego, czy pętla została wprowadzona. Podobnie każda instrukcja w tej samej kolumnie co a )jest wykonywana na końcu każdej iteracji, niezależnie od tego, czy pętla zostanie zakończona po tej iteracji.

Najpierw pokażę ci trzy programy bez większego komentarza. Poniżej znajdziesz obszerne wyjaśnienia.

Programy

"Witaj świecie!" Wariant

9(1-)v98+^++!9v+!  v88++2+!^  ! ^9-3-! v      !    v2-!55+!
8 8+ !     7v+! 1v+!88+^+!^4-!^ v8-^ !!!9v+  !^9+9+!  v5+!
     ^98++4+! ^8-! ^4-   ^ #!^6-!    ^^  #5+! v    ^2-!1+!

Jeśli używasz interpretera Python, upewnij się, że NUMERIC_OUTPUT = False.

ASCII Art N

      v2-(1-)v         
9(1-)?1-( v!  (1-55+!      0     (0)#  ))55+!
4-4+                  v^-#
     v!      v! v1-v!(1- ^(#^!0)# v! )v!
6 8+           v#

Dla ułatwienia użytkowania program ten korzysta z odczytu danych wejściowych jako liczb, ale dane wyjściowe nie mogą być liczbowe. Jeśli więc używasz zmodyfikowanego interpretera języka Python, ustaw

NUMERIC_INPUT = True
NUMERIC_OUTPUT = False

GCD

?(                         v)
? (^-(0 # v   #       ^+0)#^ !
     ^^ (##v^v+)#  0 (0 )   
      1) ^ #  - 1+(#)#

Najlepiej stosować to przy wszystkich numerycznych wejściach / wyjściach tj

NUMERIC_INPUT = True
NUMERIC_OUTPUT = True

Objaśnienia

"Witaj świecie!" Wariant

Jest to dość proste. Używam 3 głosów do sukcesywnego generowania kodów znaków dla wszystkich znaków w Prelude was made in 2005!. Zaczynam od obliczeń 8 + 9*8 = 80, które są kodem znaków P:

 9(1-)
 8 8+

Potem głównie po prostu kopiuję poprzedni kod znaku i dodam lub odejmuję różnicę do następnego. Oto kod, ale każdy z nich !zastępowany jest drukowanym znakiem (oraz _spacji i %cyfr):

9(1-)v98+^++r9v+u  v88++2+w^  _ ^9-3-a v      _    v2-%55+!
8 8+ P     7v+l 1v+e88+^+_^4-s^ v8-^ de_9v+  n^9+9+%  v5+%
     ^98++4+e ^8-d ^4-   ^ #a^6-m    ^^  #5+i v    ^2-%1+!

Finał 55+! drukuje znak nowej linii, tylko dlatego, że jest ładniejszy.

Na marginesie, liczba głosów jest dość dowolna w przypadku tego zadania, ale 3 jest dość wygodne, ponieważ jest to największa liczba, w której każdy głos może bezpośrednio uzyskać dostęp do siebie.

ASCII Art N

      v2-(1-)v         
9(1-)?1-( v!  (1-55+!      0     (0)#  ))55+!
4-4+                  v^-#
     v!      v! v1-v!(1- ^(#^!0)# v! )v!
6 8+           v#

Z 5 głosami jest to zdecydowanie jeden z najbardziej złożonych programów, jakie do tej pory napisałem. Głosy mają z grubsza następujące cele:

  1. Jedynie głos pomocnika, który przechowuje N-1 do użytku w wewnętrznej pętli.
  2. Jest to rodzaj „głównego” głosu, który odczytuje wejście, zawiera ważny przełącznik, a także zawiera zewnętrzną pętlę (tj. Tę nad rzędami).
  3. To przechowuje a 32 wygodne drukowanie spacji.
  4. Zawiera wewnętrzną pętlę (tę nad kolumnami).
  5. Umożliwia to 78wygodne wydrukowanie N.

Przejrzyjmy kod po części. Najpierw tworzę 32as -4 + 9*4i 78as 6 + 9*8:

9(1-)
4-4+

6 8+

Teraz drukuję singiel N(ponieważ zawsze go potrzebujemy) podczas czytania danych wejściowych Ni przechowywania N-1oraz N-2w dwóch pierwszych głosach:

      v2-
     ?1-

     v!

Następnie uwarunkowana jest „pętla” N-1. Na końcu pętli drugi głos jest zawsze redukowany do 0, a pętla wychodzi po pierwszej iteracji. Zasadniczo tylko to if(N > 1){...}. Po pętli wypisujemy pojedynczy znak nowej linii. Podsumowując, mamy teraz następujące ramy:

      v2-
9(1-)?1-(                               )55+!
4-4+
     v!
6 8+

Wewnątrz tego warunku, najpierw N-2spacje i pojedynczy, Naby ukończyć pierwszy rząd, a także przechowujemy N-1na pierwszym głosie do przyszłego użytku:

         (1-)v         
          v!  

             v!

Teraz prawdziwe mięso kodu. Najpierw jest zewnętrzna pętla, która drukuje N-1rzędy. Dla każdego wiersza najpierw drukujemy nowy wiersz i N. Następnie zapętlamy N-2czasy, drukując spacje lub Ns (więcej na ten temat później). I na koniec drukujemy kolejny N:

               1-55+!  

                v1-v!(               )v!
               v#

Wreszcie fajna część: wydruk każdego rzędu (i uzyskanie pozycji Nprawej). W Preludium nie ma tak naprawdę if / else, więc muszę zbudować go sam, używając dwóch pętli na różnych głosach. Warunek można łatwo uzyskać, odejmując zmienną pętli wewnętrznej i zewnętrznej - otrzymujemy, 0jeśli chcemy wydrukowaćN i coś niezerowego, jeśli chcemy wydrukować spację.

Podstawową ideą if / else w Prelude jest umieszczenie pętli po odpowiedniej wartości - kodzie „if” (lub niezerowym) i natychmiastowe wyjście z niego poprzez naciśnięcie a 0. W innym głosie zachowuje się niezerową wartość i kolejną pętlę po pętli „if”. Podczas pętli „if” umieszczasz zero na tym drugim głosie, aby zapobiec wykonaniu „else”. Istnieje pewna elastyczność, czy przesuwasz wartości zerowe na wartości niezerowe, czy po prostu odrzucasz wartość niezerową, jeśli poniżej znajduje się zero, ale jest to ogólny pomysł. Być może będziesz musiał później zrobić porządki, jeśli chcesz nadal używać odpowiedniego głosu. Oto jak wygląda kod:

                           0     (0)#
                      v^-#
                      1- ^(#^!0)# v! 

I to wszystko!

GCD

Jest to „tylko” iteracyjna implementacja algorytmu euklidesowego. Ale modulo w Preludium jest nieco denerwujące, głównie dlatego, że nie można łatwo sprawdzić, czy liczba jest dodatnia czy ujemna. Ten kod korzysta z implementacji signum, którą napisałem jakiś czas temu . To znaczy duża część kodu po prostu zamienia liczbę na -1, 0lub 1. Można to łatwo zmienić w warunek dla liczb dodatnich lub ujemnych przez dodanie lub odjęcie 1.

?(                         v)
? (^-(0 # v   #       ^+0)#^ !
     ^^ (##v^v+)#  0 (0 )   
      1) ^ #  - 1+(#)#

Tym razem mamy cztery głosy. Pierwszy głos po prostu śledzi bi zawiera główny warunek zakończenia (tj. Pętla kończy się, gdy bstaje się 0). Drugi głos zawiera ai za pomocą głosów trzech i czterech obliczeń a % b, przed zamianą wyniku na poprzedni b. Wreszcie !odbitki akiedy b == 0.

Najpierw spójrzmy na część signum :

     (0 # v   #
     ^^ (##v^v+)#
      1) ^ #  -

Numer wejściowy nznajduje się na pierwszym z tych głosów (drugi głos w pełnym programie). Wynik skończy na najniższym głosie. Pozostałe dwa głosy powinny być puste (tzn. Wypełnione zerami). Zauważ, że jeśli n == 0, wówczas obie pętle są pomijane, a dolny głos nadal zawiera 0tylko to, czego chcemy.

Jeśli njest niezerowa, wprowadzana jest pierwsza mała pętla. Naciskamy zero, aby natychmiast z niego wyjść, umieszczamy dwie kopie nna środkowym głosie i 1na dolnym. Teraz podstawową ideą jest zwiększanie jednej z kopii npodczas zmniejszania drugiej, ndopóki jedna z nich nie osiągnie zera. Robiąc to, 1głos na dole cały czas zmienia znak (co można łatwo zrobić, odejmując go 0spod stosu). Jest to ustawione tak, że gdy jedna z liczb osiągnie zero, głos dolny będzie zawierał prawidłowy znak.

Teraz modulo jest implementowane przez odejmowanie bod, aaż wynik będzie ujemny. Kiedy tak się stanie, dodajemy bjeszcze raz. To jest to:

  (^-  signum         ^+0)#
       signum      0 (0 )   
       signum   1+(#)#

Zwróć uwagę na konstrukcję if / else na dole, która jest podobna do tej, której użyłem w Zadaniu 2.


2
To naprawdę powinno być częścią samouczka Preludium.
Alex A.

21

2007 - Scratch

Scratch to język stworzony przez MIT do celów edukacyjnych. Jestem bardzo zaangażowany w to od 5 lat; więcej na ten temat później.

Wszystkie z nich można obejrzeć tutaj .

Jestem teraz bardzo rzucony i później wyjaśnię fragmenty. Mam jednak nadzieję, że są one bardzo oczywiste.

Zadanie 1

enter image description here

Zadanie 2

enter image description here

Zadanie 3

enter image description here


Czy to już później?
dfeuer

21

1972 - C

Wszyscy wiemy o C, prawda? C został stworzony w Bell Labs wraz z Uniksem. Unix został napisany głównie w C. Wszystkie współczesne pochodne uniksowe są nadal w dużej mierze napisane w C. Składnia C. wpłynęła na wiele języków programowania. Jest to prawdopodobnie najstarszy język programowania, który wciąż jest szeroko stosowany w nowych projektach.

Sam C jest potomkiem B, który, mam nadzieję, również znajdzie się na tej liście. Nie było języka programowania „A”: B jest odmianą BCPL, która z kolei jest uproszczoną wersją CPL. Żaden z tych języków nigdy nie był bardzo popularny. Jednak BCPL był językiem, w którym napisano pierwszy program „Hello World”. Innym interesującym faktem jest to, że B miał zarówno komentarze, jak /* */i //C, ale C je zrzucił //. Zostały one później ponownie wprowadzone do C ze standardem C99.

Programy C tutaj testowano z kompilatorem Unix V5 C od 1974 roku. Był to najstarszy kompilator C, jaki udało mi się znaleźć i zacząć działać, a programy te nie będą się kompilować na nowoczesnym kompilatorze C. (Jedną z wprowadzonych zmian jest to, że operatory mutacji takie jak +=kiedyś były pisane =+).

#include <... >jeszcze nie istniał. Żadna ze standardowych bibliotek nie zrobiła tego. Musiałem napisać własny atoi. Przejrzałem część kodu źródłowego V5, aby dowiedzieć się, które rzeczy są dozwolone, a które nie. Wersja, której użyłem, była pierwszą, która zawierała structs, ale ponieważ ich nie użyłem, a składnia nie zmieniła się aż do V7 (jako K&R C), może to również działać z wcześniejszymi wersjami.

Zrobiłem co w mojej mocy, aby napisać kod w tym samym stylu, w jakim wykorzystuje kod źródłowy V5. (Ale to nie jest strasznie konsekwentne.)

Zajrzyj tutaj, aby znaleźć łącza do emulatora Unix V5 i instrukcje dotyczące uruchamiania go na nowoczesnym komputerze.

Zadanie 1

main()
{
   write(1, "C was made in 1972!\n", 20);
}

Zadanie 2

atoi(str)
char *str;
{
    register num, digit;
    while (digit = *str++) {
        num =* 10;
        num =+ digit - '0';

    }
    return num;
}

N(n)
{
    register x, y;
    for (y=1; y<=n; y++) {
        for (x=1; x<=n; x++) {
            write(1, " N"+(x==1||x==y||x==n), 1);
        }
        write(1, "\n", 1);
    }
}

main(argc, argv)
char *argv[];
{
    N(atoi(argv[1]));
}

Zadanie 3

atoi(str)
char *str;
{
    register num, digit;
    while (digit = *str++) {
        num =* 10;
        num =+ digit - '0';
    }
    return num;
}

gcd(a, b)
{
    return b ? gcd(b, a%b) : a;
}

main(argc, argv)
char *argv[];
{
    printf("%d\n", gcd(atoi(argv[1]), atoi(argv[2])));
}

Wow, nigdy nie zdawałem sobie sprawy, jak bardzo zmieniło się C ... Skąd wziąłeś ten kompilator?
kirbyfan64sos

1
Kompilator jest kompilatorem dołączonym do Unixa V5. W opisie znajduje się link do postu na blogu, który pokazuje, skąd pobrać pliki i jak je uruchomić na nowoczesnym komputerze. (Jest tutaj ). Po uruchomieniu możesz pobrać na niego kod za pomocą cat > file.c. (Jak zwykle, naciśnij Ctrl-D). Również C zmieniła się mniej niż można by pomyśleć: jeśli zamienić =*i =+w atoifunkcji dla nowoczesnych ekwiwalentów *=oraz +=, nowoczesny GCC skompiluje je dobrze, a oni biegają też. Nawet prawie żadnych ostrzeżeń.
marinus

1
minnie.tuhs.org/cgi-bin/utree.pl?file=V2/c to najwcześniejszy kompilator w języku C, jaki udało mi się znaleźć (od wersji V2, z lat '72).
Oberon

20

2009 - Idris

Idris jest zależnym od typu, czystym językiem funkcjonalnym, który kładzie nacisk na faktyczną użyteczność w rzeczywistych zastosowaniach, oprócz oferowania niezwykle rygorystycznych możliwości sprawdzania, które można osiągnąć przy użyciu typów zależnych.

Zadanie 1

module Main

main : IO ()
main = putStrLn "Idris was made in 2009!"

Zadanie 2

module InN

import Data.Fin
import Data.Vect

genN : Vect n (Vect n Char)
genN = [[ if inN x y then 'N' else ' ' | x<-range ]| y<-range ]

||| Helper function, determines whether the char at coordinate (x,y)
||| is part of the letter:
inN : Fin n -> Fin n -> Bool
inN {n=S _} x y = x==0 || x==y || x==last

Ten nie jest programem, ale tylko funkcją (a dokładniej wartością zależną ), wytwarzającą pożądaną literę N jako tablicę dwuwymiarową.

$ idris ascii-n.idr 
     ____    __     _                                          
    /  _/___/ /____(_)____                                     
    / // __  / ___/ / ___/     Version 0.9.17.1-
  _/ // /_/ / /  / (__  )      http://www.idris-lang.org/      
 /___/\__,_/_/  /_/____/       Type :? for help               

Idris is free software with ABSOLUTELY NO WARRANTY.            
For details type :warranty.
Type checking ./ascii-n.idr
*ascii-n> genN {n=4}
[['N', ' ', ' ', 'N'],
 ['N', 'N', ' ', 'N'],
 ['N', ' ', 'N', 'N'],
 ['N', ' ', ' ', 'N']] : Vect 4 (Vect 4 Char)

Zadanie 3

module gcd

gcd' : Nat -> Nat -> Nat
gcd' a Z = a
gcd' a b = gcd' b $ a`mod`b

Zauważ, że musiałem wybrać nazwę, gcd'ponieważ jest gcdona już zdefiniowana w preludium Idris.

Type checking ./gcd.idr
*gcd> gcd' 8 12
4 : Nat
*gcd> gcd' 12 8
4 : Nat
*gcd> gcd' 234 876
6 : Nat

To wygląda tak, jakby wziął Haskell, zamieniłem :i ::, i zmienił _się Z.
wchargin

@WChargin Zjest tak naprawdę konstruktorem 0 : Nat. Podkreślenie jest używane w Idris, tak jak w Haskell.
przestał się obracać przeciwnie do zegara

och, cóż, proszę bardzo! :)
wchargin

19

2014 - Pyth

Ponieważ mamy CJam, równie dobrze możemy mieć Pyth dla kompletności :)

Pyth jest językiem golfowym autorstwa @isaacg, który kompiluje się do Pythona. Jest to godne uwagi ze względu na proceduralność i stosowanie notacji przedrostkowej. Pyth po raz pierwszy pojawił się około czerwca 2014 r .

"Witaj świecie!" Wariant

"Pyth was made in 2014!

Zwróć uwagę na brak zamykającego cytatu, który jest opcjonalny, jeśli program Pyth kończy się ciągiem.

ASCII Art N

VQ+\Nt+P++*Nd\N*t-QNd\N

Wypróbuj online . Odpowiednikiem Pythona jest:

Q = eval(input())
for N in range(Q):
    print("N"+((" "*N+"N"+(Q-N-1)*" ")[:-1]+"N")[1:])

Lub rozwinięte (pierwsza i trzecia linia są niejawne):

Q = eval(input())                                        # 
for N in range(Q):                                       #   VQ
    print(                                          )    # 
          "N"+                                           #     +\N
              (                                )[1:]     #        t
                                           +"N"          #         +              \N
               (                     )[:-1]              #          P
                         +(Q-N-1)*" "                    #           +      *t-QNd
                     +"N"                                #            +   \N
                " "*N                                    #             *Nd

GCD

=GvwWQAGQ,Q%GQ)G

Ten program wykorzystuje algorytm euklidesowy i przyjmuje dwie liczby oddzielone znakiem nowej linii. Wypróbuj online .

Q = eval(input())     #
G = eval(input())     #    =Gvw
while Q != 0:         #        WQ
  G, Q = Q, G % Q     #          AGQ,Q%GQ)
print(G)              #                   G

i.uQjest jeszcze krótszy, jeśli użyjemy wbudowanego GCD. Jest to równoważne print(gcd(*eval(input())))(przyjmowanie dwóch liczb oddzielonych przecinkami jako danych wejściowych).


Drat - miałem zamiar zrobić Pyth xP
theonlygusti

@isaacg Nie mogę przestać się zastanawiać i równie dobrze mogę zapytać tutaj: czy pyth został zainspirowany przez pyga w jakikolwiek sposób, kształt lub formę?
Aprıʇǝɥʇuʎs,

@ Iıʇǝɥʇuʎs Widziałem PYG przed zrobieniem Pytha i mogło to mieć wpływ na podejście koncepcyjne 1 znak - 1. Jeśli jednak coś zainspirowało Pytha, to prawdopodobnie był to golf.
isaacg

17

1964 - Dartmouth BASIC

PODSTAWOWY to rodzina uniwersalnych języków programowania wysokiego poziomu, których filozofia projektowania podkreśla łatwość użycia. W 1964 roku John G. Kemeny i Thomas E. Kurtz zaprojektowali oryginalny język BASIC w Dartmouth College w New Hampshire. Chcieli umożliwić uczniom z dziedzin innych niż przedmioty ścisłe i matematyczne korzystanie z komputerów.

Patrzę na ten podręcznik BASIC z 1964 roku i na ten emulator Darthmouth Time Sharing System, na którym działał. Serwer nadal działa, ale niestety rejestracja konta wydaje się niemożliwa. Na razie te programy powinny teoretycznie działać:

Zadanie 1

10 PRINT "BASIC WAS MADE IN 1964"
20 END

Zadanie 2

10 READ N
15 FOR Y = 1 TO N STEP 1
20 FOR X = 1 TO N STEP 1
25 IF X = 1 THEN 50
30 IF X = N THEN 50
35 IF X = Y THEN 50
40 PRINT " ",
45 GO TO 55
50 PRINT "N",
55 NEXT X
60 PRINT
65 NEXT Y
70 DATA 5
75 END

Wyprowadzanie czegoś takiego:

N                       N
N     N                 N
N           N           N
N                 N     N
N                       N

Zwróć uwagę, jak dane wejściowe są wpisywane jako część programu ( 70 DATA 5); READsposób wskazówki na górze pobiera dane stamtąd. Nie ma konkatenacji łańcuchów, ale rozdział 3.1 instrukcji opisuje, jak to zrobićPRINT wyniki są zapisywane w tabelarycznych „strefach” na wyjściu.

Zadanie 3

Wolna wersja algorytmu Euclid:

10 READ A, B
20 IF A = B THEN 80
30 IF A < B THEN 60
40 LET A = A - B
50 GO TO 20
60 LET B = B - A
70 GO TO 20
80 PRINT A
85 DATA 144, 250
90 END

Wyjście:

2

Wreszcie ktoś zrobił BASIC.
marinus

16

2010 - WTFZOMFG

WTFZOMFG to ezoteryczne języki oparte na Brainfuck. Został stworzony przez Jaya Songdahla w 2010 roku. „WTFZOMFG” to skrót od „What's That Function? Zen Optimized Malicious File Gophers!” .

Oto kompilator dla systemów * nix .

Zadanie 1

'WTFZOMFG was made in 2010!\n"

Zadanie 2

/&(-.N%3 >&>s-{-(-. ).N}>{-(-. ).N}_0 '\n")

Wyjaśnienie:

Przepraszam. Nie jestem dobry w pisaniu wyjaśnień.

/                                           # read the number and store it in cell 0
 &                                          # copy it to cell 1
  (                                         # loop while cell 0 isn't 0
   -                                        # decrease the value of cell 0
    .N                                      # print "N"
      %3                                    # copy cell 0 to cell 3
                                            # a space must be added after the number. I don't know if it's a bug of the compiler or a feature.
         >                                  # move to cell 1
          &                                 # copy cell 1 to cell 2
           >                                # move cell 2
            s                               # let cell 2 = cell 2 - cell 3
             -                              # decrease the value of cell 2
              {                             # if cell 2 isn't 0
               -                            # decrease the value of cell 2
                (-. )                       # while cell 2 isn't 0, decrease it and print " "
                     .N                     # print "N"
                       }                    # end if
                        >                   # move cell 3
                         {                  # if cell 3 isn't 0
                          -                 # decrease the value of cell 3
                           (-. )            # while cell 3 isn't 0, decrease it and print " "
                                .N          # print "N"
                                  }         # end if
                                   _0       # move to cell 0
                                      '\n"  # print a newline
                                          ) # 

Zadanie 3

/>>/(<<&>dm<s&>>%0 <&>)<<\

Algorytm euklidesowy. WTFZOMFG nie ma polecenia mod, więc muszę użyć d(podzielić), m(pomnożyć) i s(odjąć).


16

2009 - Idź

Go to język programowania opracowany przez Google. Rozwój rozpoczął się w 2007 roku, ale Go ogłoszono w listopadzie 2009 roku.

Go to język pisany statycznie, na który wpływa C, co podkreśla zwięzłość, prostotę i bezpieczeństwo.

Zadanie 1:

package main
import "fmt"

func main(){
    fmt.Println("Go was made in 2009!")
}

Pierwszy wiersz deklaruje pakiet kodu. Nawet prosty przykład drukowania jednej linii musi być częścią jednego pakietu. Plik wykonywalny jest zawsze wywoływany main.

Zadanie 2:

package main

import (
        "fmt"
        "strings"
)

func main(){
    var n int
    fmt.Scan(&n)

    for i := 0; i < n; i++ {
        a := make([]string, n, n)
        for j := 0; j < n; j++ { a[j] = " " }

        a[0] = "N"
        a[i] = "N"
        a[n-1] = "N"

        s := strings.Join(a, "")
        fmt.Println(s)
    }
}

Go ma dość zwięzłą deklarację zmiennej ( i := 0jest taka sama jak var i int = 0), a kompilator określa typ. Jest to zwykle funkcja bardziej powszechna w dynamicznych językach. Za pomocą tej krótkiej notacji bardzo łatwo jest również przypisywać funkcje do zmiennych ( f := func(x int) int {/* Code */}) i tworzyć Zamknięcia.

Zadanie 3:

package main

import "fmt"

func gcd(a, b int) int {
    for b != 0 {
        a, b = b, a%b
    }
    return a
}

func main(){
    var a, b int
    fmt.Scan(&a)
    fmt.Scan(&b)

    fmt.Println(gcd(a, b))
}

Tutaj możesz zobaczyć a, b = b, a%bskładnię, co jest naprawdę miłe. Nie znam dokładnej nazwy, ale w Pythonie nazywa się to rozpakowywaniem krotek. W ten sam sposób możesz zwrócić wiele wartości z funkcji ( func f() (int, string) { return 42, "Hallo"}).

Kolejną rzeczą występującą w tym kodzie jest pętla. Pętla for jest jedyną pętlą w Go. Pętle while i pętle do-while nie istnieją. Ale możesz łatwo utworzyć odpowiednik dla pętli while for condition {}lub nieskończonej for {}.


16

1991 - Python

Historia języka

Pod koniec lat osiemdziesiątych Guido van Rossum zaczął wymyślać Python jako hobby. Jego nazwa pochodzi od Flying Circus Monty Pythona, brytyjskiego programu telewizyjnego, którego Rossum jest fanem. Pierwsza implementacja Pythona rozpoczęła się w 1989 roku i została wydana w 1991 roku. Z biegiem lat zyskała na popularności, stając się językiem wyboru wielu wprowadzających kursów informatyki.

"Witaj świecie!" Wariant

print("Python was made in 1991!")

Zwróć uwagę na nawiasy wokół danych wejściowych do print. Chociaż ta składnia działa w języku Python 2, zazwyczaj w języku Python 2 można pominąć te nawiasy. Są one jednak wymagane w Pythonie 3. Zgodnie z sugestią Zacha Gatesa, w nawiasach są używane wszystkie elementy, aby zapewnić, że przedstawiony tu kod będzie działał w różnych wersjach.

ASCII Art N

def asciin(n):
    if n == 1:
        print("N")
    else:
        print("N" + " "*(n-2) + "N")

        for i in range(2, n):
            print("N" + " "*(i-2) + "N" + " "*(n-i-1) + "N")

        print("N" + " "*(n-2) + "N")

Funkcje są definiowane za pomocą def. Łączenie łańcuchów odbywa się za pomocą +i powtarzania łańcuchów za pomocą *.

GCD

def gcd(a, b):
    if b == 0:
        return(a)
    else:
        return(gcd(b, a % b))

Zauważ, że Python wymaga strukturalnej białej spacji.


16

1968 - Algol 68

Algol 68 został zdefiniowany przez grupę roboczą IFIP 2.1 jako następca Algolu 60.

Jest to język zorientowany na wyrażenie, w którym wszystko ma wartość. Jest również ortogonalny, w którym możesz użyć dowolnego konstruktu w jakikolwiek sposób. Oznacza to, że wyrażenia mogą znajdować się na przykład w RHS i LHS zadania.

Wszystkie struktury kontrolne mają zarówno formę skróconą, jak i długą z użyciem wyrażeń. Pozwala także na definicje operatorów.

Cele języka są cytowane jako:

Główne cele i zasady projektowania ALGOL 68:

  • Kompletność i przejrzystość opisu
  • Projekt ortogonalny,
  • Bezpieczeństwo,
  • Wydajność
  • Sprawdzanie trybu statycznego
  • Parsowanie niezależne od trybu
  • Niezależna kompilacja
  • Optymalizacja pętli
  • Reprezentacje - w minimalnych i większych zestawach znaków

Programy te zostały przetestowane za pomocą interpretera Algol 68 Genie , który jest kompletną implementacją języka.

Niektóre funkcje, które mogą być inne dla współczesnych programistów, to to, że puste instrukcje nie są dozwolone. Nie możesz po prostu dodawać ;wszędzie. Musisz użyć tego SKIPoświadczenia, jeśli chcesz jawnie nic nie mieć. Umożliwiło to również bardzo łatwe kodowanie współbieżnych programów. Algol 68 również w szczególności użył słów kluczowych wstecz jako terminatorów, takich jak esac , od , fi itp.

Język miał reprezentację używaną do pisania kodu, który używał wielu czcionek reprezentujących pogrubione słowa kluczowe , a identyfikatory pisano kursywą . W tym czasie i prawdopodobnie nadal żaden kompilator nie wdrożył tej funkcji projektu. Język pozwalał na kilka różnych konkretnych reprezentacji programów wykorzystujących tryby stropowania . Umożliwiło to przygotowanie programów przy użyciu ograniczonych zestawów znaków, takich jak te, które można znaleźć na komputerach w latach 60. XX wieku. Rozważ krótki fragment programu, który byłby reprezentowany jako:

jeśli i < 0, to pomiń fi

Można to przygotować dla kompilatora w trybie głównego stropowania, ponieważ:

'IF' I 'LT' 0 'THEN' 'SKIP' 'FI'

W trybie stropowania kropek byłoby to:

.IF I .LT 0 .THEN .SKIP .FI

W przypadku trybu stropowania byłoby to:

IF i < 0 THEN SKIP FI

Mam wielką sympatię do tego języka, ponieważ pracowałem nad jedną z implementacji kompilatora, a także programowałem w nim wyłącznie przez wiele lat.

Zadanie 1

drukuj ((„Algol 68 powstał w 1968 roku!”, nowa linia ))

Należy tutaj zwrócić uwagę na podwójne nawiasy. To dlatego, że drukuj jest funkcją, która przyjmuje pojedynczy argument, który jest tablicą zmiennej długości unii wszystkich typów. Wewnętrzny nawias to konstruktor tablicy. W ten sposób obsługiwany jest polimorfizm w tym silnie typowanym języku.

W przypadku trybu stropowania:

print (("Algol 68 was made in 1968!", newline))


C:\>a68g HelloWorld.a68
Algol 68 was made in 1968!

Zadanie 2

     int n ;
     czytaj (( n ));
     dla i od 1 do n zrobić
          dla j od 1 do n zrobić
               ¢ tu używamy skrócona IF klauzula ¢
               druku ((( j = 1 OR j = i LUB j = n |
                    "N"
               |
                    ""
               )))
          od ;
     print (( nowa linia))
     od

W przypadku trybu stropowania:

 INT n;
 read ((n));
 FOR i FROM 1 TO n DO
        FOR j FROM 1 TO n DO
            CO here we use an abbreviated IF clause CO
            print (( ( j = 1 OR j = i OR j = n |
                 "N"
            |
                 " "
            ) ))
        OD ;
        print ((newline))
    OD

C:\>a68g ASCIIart.a68
8
N      N
NN     N
N N    N
N  N   N
N   N  N
N    N N
N     NN
N      N

Zadanie 3

     ¢ możemy zdefiniować własnych operatorów w Algolu 68 ¢
     op % = ( int a , b ) int :
          (( b = 0 |
               a
          |
               b % ( a mod b )
          ));
     int i , j ;
     czytać (( i , j ));
     drukuj (( i % j , nowa linia ))

W przypadku trybu stropowania:

COMMENT we can define our own operators in Algol 68 COMMENT
OP % = ( INT a, b) INT:
    ((b = 0 |
        a
    |
       b % (a MOD b)
    ));
INT i,j;
read((i,j));
print(( i % j , newline))


C:\>a68g GCD.a68
4 12
         +4

7
Były to prawdopodobnie pierwsze programy Algol 68, które napisałem i wykonałem przez ponad 30 lat. Uznałem, że jest tak poruszający, że doprowadził mnie do łez. Nigdy nie zdawałem sobie sprawy z „Hello World!” program może być tak emocjonujący!
Brian Tompsett - 汤 莱恩

1
Tak bardzo nie mogłem się doczekać Języków z lat 60. i byłem gotowy na BCPL, Simulę, CORAL66, Fortran 66, PL / 1, SNOBOL4, POP-1 i całą masę innych rzeczy, tylko po to, by odkryć, że mam takie zasady czekać 5 lat języków ... Przynajmniej ktoś ma do dyspozycji bogatą bruzdę.
Brian Tompsett - 汤 莱恩

Naprawdę fajnie jest zobaczyć różnice między Fortran66 (kompletny bałagan przemocy z kartami dziobowymi), APL (dziwny bałagan symboli supermocy) i Algol68, który jest naprawdę piękny. Dzisiaj trzeba by szukać języków ezoterycznych, aby znaleźć tak wiele różnych podejść ... wtedy był to raczej główny nurt, prawda?
przestał się obracać przeciwnie do zegara

Oczywiście, poprawiony raport został opublikowany dopiero w 1976 roku, prawda? Przynajmniej taki jest rok praw autorskich, który podaje Springer. A skan, który znalazłem, wspomina 1978 r.
Rhialto,

[1] A. van Wijngaarden (red.), Bl Mailloux, 1.EL Peck, CBA Koster, Raport o języku algorytmicznym ALGOL 68, Numer. Matematyka 14 (1969) 79-218; także w Kibenietika 6 (1969) i 7 (1970). [2] A. van Wijngaarden, Bl Mailloux, 1.EL Peck, CBA Koster, M: Sintzoff, CBLindsey, LGLT Meertens i RG Fisker, Zmieniony raport na temat języka algorytmicznego ALGOL 68, Acta Informat. 5 (1975) części 1-3 (przedruki opublikowane przez Springera, Berlin, a także jako Mathematical Center Tract 50 przez Mathematisch Centrum, Amsterdam); także w SIGPLAN Notices 12 (5) (1977)
Brian Tompsett - 汤 莱恩

16

1962 - SNOBOL

„StriNg Oriented and symBOlic Language”. Najpierw najwyraźniej nazywał się Symbolicznym Tłumaczem Wyrażeń, „SEXI”, który następnie musiał zostać zmieniony, aby zapobiec zarumienieniu się nerdów z lat 60-tych podczas przesyłania pracy. Prawdziwa historia.

Był to jeden z pierwszych języków, który mógł natywnie radzić sobie z łańcuchami i wzorcami. Rzeczywiście, pierwsza wersja SNOBOL miała ciąg jako jedyny typ danych. Matematyka została następnie wykonana przez parsowanie. Pierwszej implementacji dokonano na IBM 7090. Wydaje się, że już dawno minęła, przynajmniej nie mogłem jej znaleźć. Znalazłem oryginalny artykuł opisujący go, a także interpreter SNOBOL3 w Javie, który można uruchomić na nowoczesnym komputerze .

Pierwszy SNOBOL miał prawie tylko dopasowywanie wzorców i podstawową arytmetykę. SNOBOL 3 następnie dodał funkcje i zmienił I / O, ale poza tym wydaje się, że pozostał kompatybilny wstecz. SNOBOL 4 zmienił składnię i stamtąd rozwinął się w Icon , który utrzymuje dopasowanie wzorca, ale poza tym wygląda prawie jak „normalny” język programowania.

Programy, które napisałem, używają tylko funkcji opisanych w oryginalnym artykule, więc powinny działać z oryginalnym SNOBOL, z wyjątkiem I / O, które zrobiłem w stylu SNOBOL3, aby mógł je uruchomić interpreter Java. Z pracy wynika, że ​​różnica polega na tym, że SNOBOL1 używa dopasowania wzorca ze specjalną SYSzmienną, podczas gdy SNOBOL3 używa zmiennych wejściowych i wyjściowych:

  • Wejście:
    • 1 SYS .READ *DATA*
    • 3) DATA = SYSPPT
  • Wynik:
    • 1 SYS .PRINT 'A STRING' AND VARIABLES
    • 3) SYSPOT = 'A STRING' AND VARIABLES

Dokonanie tych zamian powinno dać ci „prawdziwy” SNOBOL 1. Oczywiście, nie możesz go uruchomić.

Zadanie 1

START   SYSPOT = 'SNOBOL WAS MADE IN 1962!'

Zadanie 2

Pokazuje matematykę, obsługę łańcuchów i kontrolę przepływu. SNOBOL3 ma przydatne funkcje, takie jak EQsprawdzanie równości; oryginalny SNOBOL nie, więc ich nie użyłem.

* READ N FROM INPUT
START   SYSPOT = 'SIZE?'
        SZ = SYSPPT

* INITIALIZE
        CS = ''
        ROW = '0'

* OUTPUT PREVIOUS ROW AND START NEXT ONE
ROW     COL = '0'
        SYSPOT = CS
        CS = ''

COL     SUCC = 'N'
        EQ1 = COL
        FAIL = 'CHKE'
        EQ2 = '0'         /(EQUAL)
CHKE    FAIL = 'CHKR'
        EQ2 = SZ - '1'    /(EQUAL)
CHKR    FAIL = 'SPACE'
        EQ2 = ROW         /(EQUAL)

* CONCATENATE THE RIGHT CHARACTER TO THE CURRENT LINE         
SPACE   CS = CS ' '       /(NEXT)
N       CS = CS 'N'       /(NEXT)

* FOR NUMBERS, SUBSTRING MATCH IS ENOUGH IF IT IS KNOWN A<=B
NEXT    COL = COL + '1'
        COL SZ            /F(COL)
        ROW = ROW + '1'
        ROW SZ            /F(ROW)S(FIN)

* THERE SEEMS TO BE NO EQUALITY CHECK, JUST SUBSTRING MATCHING
* OF COURSE, EQ1 == EQ2 IFF EQ1 CONTAINS EQ2 AND VICE VERSA
* THIS ALSO ILLUSTRATES INDIRECTION
EQUAL   EQ1 EQ2           /F($FAIL)
        EQ2 EQ1           /S($SUCC)F($FAIL)

* OUTPUT THE LAST LINE
FIN     SYSPOT = CS     

Zadanie 3

Najpierw nudny. Jedyną rzeczą wartą uwagi jest sprawdzenie mniejsze niż, pokazujące dokładnie, jak naprawdę był zorientowany na łańcuch SNOBOL: (B - A) '-'oznacza „czy wynik BA zawiera minus?”. SNOBOL3 też może LE(B,A), ale SNOBOL 1 nie mógł (przynajmniej papier o tym nie wspomina).

* READ A AND B
START   SYSPOT = 'A?'
        A = SYSPPT
        SYSPOT = 'B?'
        B = SYSPPT

* GCD LOOP
STEP    '0' (A - B)          /S(DONE)
        (B - A) '-'          /S(AB)F(BA)
AB      A = A - B            /(STEP)
BA      B = B - A            /(STEP)
DONE    SYSPOT = 'GCD: ' A

Oczywiście, jeśli masz język oparty całkowicie na ciągach i dopasowywaniu wzorców, szkoda byłoby nie korzystać z dopasowywania i zastępowania wzorców. Tak oto jest jeden z tych GCD opartych na jednostkach, w tym procedury konwersji do i z jedności.

* READ A AND B
START   SYSPOT = 'A?'
        A = SYSPPT
        SYSPOT = 'B?'
        B = SYSPPT

* CONVERT TO UNARY
        UNA.IN = A
        UNA.FIN = 'ADONE'          /(UNA)
ADONE   A = UNA.R
        UNA.IN = B
        UNA.FIN = 'BDONE'          /(UNA)
BDONE   B = UNA.R


* USE STRING MATCHING TO FIND GCD
STEP    '' B                       /S(GDONE)
MATCH   A B =                      /S(MATCH)
        C = B
        B = A
        A = C                      /(STEP)

* CONVERT BACK TO DECIMAL
GDONE   DEC.IN = A
        DEC.FIN = 'DONE'           /(DEC)
DONE    SYSPOT = 'GCD: ' DEC.R     /(FIN)

***************************** 
* DECIMAL TO UNARY SUBROUTINE
UNA     UNA.R =
UNA.DGT UNA.IN *.DGT/'1'* =        /F($UNA.FIN)
        .X = UNA.R
        UNA.R =
UNA.MUL .X *.Y/'1'* =              /F(UNA.ADD)
        UNA.R = UNA.R '##########' /(UNA.MUL)
UNA.ADD '1' .DGT                   /S(UNA.1)
        '2' .DGT                   /S(UNA.2)
        '3' .DGT                   /S(UNA.3)
        '4' .DGT                   /S(UNA.4)
        '5' .DGT                   /S(UNA.5)
        '6' .DGT                   /S(UNA.6)
        '7' .DGT                   /S(UNA.7)
        '8' .DGT                   /S(UNA.8)
        '9' .DGT                   /S(UNA.9)
        '0' .DGT                   /S(UNA.DGT)
UNA.1   UNA.R = UNA.R '#'          /(UNA.DGT)
UNA.2   UNA.R = UNA.R '##'         /(UNA.DGT)
UNA.3   UNA.R = UNA.R '###'        /(UNA.DGT)
UNA.4   UNA.R = UNA.R '####'       /(UNA.DGT)
UNA.5   UNA.R = UNA.R '#####'      /(UNA.DGT)
UNA.6   UNA.R = UNA.R '######'     /(UNA.DGT)
UNA.7   UNA.R = UNA.R '#######'    /(UNA.DGT)
UNA.8   UNA.R = UNA.R '########'   /(UNA.DGT)
UNA.9   UNA.R = UNA.R '#########'  /(UNA.DGT)

*****************************
* UNARY TO DECIMAL SUBROUTINE
DEC     DEC.R =
DEC.DGT '' DEC.IN                  /S($DEC.FIN)
        .X = DEC.IN
        DEC.IN =
DEC.DIV .X '##########' =          /F(DEC.ADD)
        DEC.IN = DEC.IN '#'        /(DEC.DIV)
DEC.ADD '' .X                      /S(DEC.0)
        '#' .X                     /S(DEC.1)
        '##' .X                    /S(DEC.2)
        '###' .X                   /S(DEC.3)
        '####' .X                  /S(DEC.4)
        '#####' .X                 /S(DEC.5)
        '######' .X                /S(DEC.6)
        '#######' .X               /S(DEC.7)
        '########' .X              /S(DEC.8)
        '#########' .X             /S(DEC.9)
DEC.0   DEC.R = '0' DEC.R          /(DEC.DGT)
DEC.1   DEC.R = '1' DEC.R          /(DEC.DGT)
DEC.2   DEC.R = '2' DEC.R          /(DEC.DGT)
DEC.3   DEC.R = '3' DEC.R          /(DEC.DGT)
DEC.4   DEC.R = '4' DEC.R          /(DEC.DGT)
DEC.5   DEC.R = '5' DEC.R          /(DEC.DGT)
DEC.6   DEC.R = '6' DEC.R          /(DEC.DGT)
DEC.7   DEC.R = '7' DEC.R          /(DEC.DGT)
DEC.8   DEC.R = '8' DEC.R          /(DEC.DGT)
DEC.9   DEC.R = '9' DEC.R          /(DEC.DGT)

FIN     START

Doskonała praca w tle! Niewiele w 1961 roku - wygląda na to, że COMIT to wszystko, co mamy ...
Brian Tompsett - 汤 莱恩

15

2012 - TypeScript

TypeScript to darmowy i otwarty język programowania opracowany i obsługiwany przez Microsoft.

Głównym celem jest: dowolna przeglądarka. Dowolny host. Dowolny system operacyjny. Otwarte źródło. Został wydany w dniu październiku 2012 roku

Witam TypeScript

Task1(name:string,year:number) {
    return name + " was made in "+ year +"!";
}

ASCII Art

Task2(n:number,separator:string,space:string) {
    var result:string = "";
    for (var k = 0; k < n; k++)
    {
        for (var j = 0; j < n; j++)
        {
            var i = ((n * k) + j) % n;
            result+=(i == 0 || i == n - 1 || i == k) ? "N" : space;
        }
        result+=separator;
    }
    return result;
}

GCD

Task3(a:number,b:number) {
    while (a != 0 && b != 0)
        {
            if (a > b)
                a %= b;
            else
                b %= a;
        }

        if (a == 0)
            return b;
        else
            return a;
}

wypróbuj online i zrzuć go z ekranu .


4
Zapomniałeś wspomnieć o jednej rzeczy: TypeScript jest nadzbiorem Javascript z kilkoma zmianami składni i pozwala na (?) Zmienne i argumenty o silnym typie.
Ismael Miguel,

1
O mój boże, coś otwartego przez MS!
Mega Man

15

2011 - Dart

Dart to język programowania Open Source opracowany przez Google, który został opracowany jako zamiennik Javascript (chociaż kompiluje się w javascript). Zostało to zaprezentowane przez Google w 2011 roku podczas konferencji GOTO.

"Witaj świecie!" Wariant:

main() {
  print('Dart was made in 2011!');
}

ASCII Art N:

Metoda Bruteforce działa na 0 (n²), ale tak naprawdę nie powinna mieć znaczenia, chyba że użyjesz gigantycznej liczby.

asciiN(int number){
    if(number == 1){
        print('N');
    }else{
        for(var i = 1; i <= number; i++){
            String currentLine = "";
            for(var j = 1; j <= number; j++){
                if(j==1 || j == number || j == i){
                    currentLine = currentLine + "N";
                }else{
                    currentLine = currentLine + " ";
                }
            }
            print(currentLine);
        }
    }
}

GCD

prosta metoda Euclid przeniesiona z Snap! przykład powyżej.

int gcd(int first, int second){
if(second > first){
   return gcd(second, first);
    }else{
        if(first == 0){
            return second;
        }else{
            if(second ==0){
                return first;
            }else{
                return gcd(second, first-second);
            }
        }
    }
}

5
Nie sądzę, że można wygenerować obraz x n ASCII w mniej niż O (n²).
Paŭlo Ebermann

@ PaŭloEbermann Nie znam się na dużej notacji O ani na tym, jak obliczyć złożoność, ale przykład Julii wygląda na to, że nie jest to O (n²).
Nzall,

@AlexA. Funkcja println () drukuje ciąg n znaków. Myślę, że wywołanie funkcji wymaga co najmniej czasu O (n) do wykonania. W pętli, więc O (n²) dla całego programu.
Paŭlo Ebermann

@AlexA. Myślę, że to, o czym mówi Ebermann, polega na tym, że w funkcji drukowania masz operacje łączenia N łańcuchów. oboje wykonujemy konkatenacje łańcuchów n² w naszych funkcjach. Robię je raz na iterację w wewnętrznej pętli, robisz je dla każdego println ().
Nzall,

1
Gdyby to nie była sztuka ascii, O (n) wyświetlałoby N. (narysuj 3 linie na ekranie, każda linia to O (n), a zatem złożoność O (n)). Lub, można powiedzieć, renderowanie N ma złożoność O (N) ... hehe
rodolphito

15

2010 - Rdza

Rust to skompilowany język programowania ogólnego przeznaczenia, opracowany przez Mozilla Research, z wieloma paradygmatami. Został zaprojektowany jako „bezpieczny, współbieżny, praktyczny język”, obsługujący style czysto funkcjonalne, współbieżne z aktorem, imperatywno-proceduralne i obiektowe. Wikipedia

Zadanie 1

fn main()
{
    println!("Rust was made in 2010!");
}

Zadanie 2

fn main()
{
    // get commandline arguments
    // "test 3"
    let args : Vec<_> = std::env::args().collect();

    // convert 2nd argument to integer
    let n = u32::from_str_radix( args[1].as_ref(), 10 ).unwrap();
    print_n( n );
}

fn print_n( n: u32 )
{
    for y in range( 0, n )
    {
        for x in range( 0, n )
        {
            if x == 0 || x == y || x + 1 == n
            {
                print!("N");
            }
            else
            {
                print!(" ");
            }
        }
        println!("");
    }
}

Wyjaśnienie:

if x == 0 || x == y || x + 1 == n

dba o drukowanie tylko w pionie (po lewej i po prawej |) i po przekątnej ( \)

Zadanie 3

prosta implementacja algorytmu Euclidean

fn main()
{
    // get commandline arguments
    // "test 453 3"
    let args : Vec<_> = std::env::args().collect();

    // convert 2nd and 3rd argument to integers
    let a = u32::from_str_radix( args[1].as_ref(), 10 ).unwrap();
    let b = u32::from_str_radix( args[2].as_ref(), 10 ).unwrap();
    let g = gcd( a, b );
    println!( "GCD of {} and {} is {}", a, b, g );
}

fn gcd( mut a: u32, mut b: u32 ) -> u32
{
    while b != 0
    {
        let c = a % b;
        a = b;
        b = c;
    }
    return a;
}

Czy możesz dodać fragment pokazujący, jak wprowadzić dwie liczby całkowite oddzielone spacją od standardowego wejścia?
Zero Fibre

3
Czy Rust został wyprodukowany w 2010 roku? Oś czasu języków programowania mówi tak, ale faktyczny artykuł mówi, że został ogłoszony dopiero w 2010 r. (Faktycznie 2011, o czym świadczy odniesienie ), a ta wersja 0.2 została wydana w 2012 r.
EMBLEM

1
@SampritiPanda, spójrz na hastebin.com/raw/lapekowogu
wasikuss

1
Wygląda nieco nowocześnie. Czy może to skompilować jako pierwsza <s> wydana </s> opublikowana działająca wersja kompilatora?
Vi.

15

2015 - Muffin MC

Muffin MC jest kompletnym, zabawnym (ale poważnym), funkcjonalnym i minimalistycznym makro-językiem Turinga napisanym przez Francka Porchera ( http://franckys.com ) w połowie lutego 2015 r. Z konieczności jako (szybkie) narzędzie do wzmocnienia arkusz kalkulacyjny, który ma być używany jako jedyny kontroler front-end do pilotowania i kierowania wszystkimi operacjami związanymi z zapasami związanymi z witryną handlową opartą na Prestashop dla nowej marki modowej Tahitian: Mutiny Tahiti ( http://mutinytahiti.com - wkrótce będzie uruchomiona).

Muffin MC jest skrótem dla MU maleńkim F unctional F lexible W linii M acro C ommand języku.

Aby spełnić nasze wymagania, podstawowe funkcje Muffin MC zostały zaprojektowane wokół elastycznych i wydajnych wbudowanych konstrukcji semantycznych pierwszej klasy, takich jak iteratory , leniwa ocena , funkcje wielofunkcyjne , łańcuch znaków .

Muffin MC wywodzi się z (pragmatycznego) programowania funkcjonalnego, FLisp i Perl. W pełni obsługuje rekurencyjność (bez jakiejkolwiek optymalizacji), jest dynamicznie typowany i dynamicznie skalowany (płytkie wiązanie). Oferuje swoim użytkownikom tylko jedną strukturę danych, oprócz podstawowych typów danych atomów (atomów, łańcuchów, cyfr): list!

Semantyka listy Muffin MC (rodzaj) zapożycza się na semantyce power-set , czyli:

  1. Wszystko Muffin MC operacje dają listę, być może pustą.
  2. Dostęp do dowolnego elementu listy zawsze daje listę z jedną wartością utworzoną z tego elementu (pomyśl o tym jako o singletonie).
  3. Pusta lista jest neutralnym elementem operacji na liście.

Aby się z tym pogodzić, pomocne mogą być:

  • Można wizualizować listę jako element zestawu mocy listy, który ma największą liczność.
  • Wizualizuj element listy jako element zestawu mocy listy, który jest singletonem utworzonym z tego elementu.
  • Wizualizuj pustą listę jako pusty zbiór; to jest jedynym elementem zestawu mocy pustego zestawu.

Dlatego dostęp do pustego elementu listy daje pustą listę, a nie błąd! Rzeczywiście, Muffin MC stara się rzucić jak najmniej błędów, rozszerzając w ten sposób semantykę wielu tradycyjnych operacji.

Zadanie 1

#(say "MuffinMC was born in 2015 out of necessity !")

#(...)to makropolecenie Muffin MC do zastosowania funkcji na nieudokumentowanej liście argumentów, tutaj wbudowana funkcja sayzapożyczona z Perla.

#(say 1 2 3 ...) jest funkcjonalnie identyczny z map {say $_} (1,2,3,...)

Zadanie 2

Zdefiniuj funkcję ascii-art():

=(ascii-art
    '( =(*  x   #(2- $(_1))
        I   I( *($(x) " ") N)
            foo '( #(. #(I $(x))) ))
    #(say ?( #(== $(_1) 1) N "N#(map foo #(.. 1 $(_1)))N" ))
 ))

Ascii-art()najkrótsza forma robocza (88 bajtów):

=(f'(=(* x#(2-)I I(*($(x)" ")N)g'(#(.#(I$(x)))))#(say?(#(==$(_1)1)N"N#(map g#(..))N"))))
  • =(var val...)to makropolecenie Muffin MC, aby zdefiniować zmienną lub przypisać ją ponownie.

  • $(var)to makropolecenie Muffin MC umożliwiające dostęp do wartości zmiennej. Naturalnie akceptuje formularz, $(v1 v2 ...)aby uzyskać dostęp do wielu zmiennych jednocześnie.

  • =(* var1 val1 var2 val2 ...)jest rozszerzeniem makropolecenia Muffin MC=(...) do obsługi równoległych przypisań.

  • Zmienne _1, _2... mają dynamiczny zasięg (płytki mechanizm wiązania) i są automatycznie ustawiane tak, aby wiązały się z argumentami funkcji. Zapożyczone z Perl5, zmienne systemowe #(liczba argumentów) i @(lista argumentów) są również ustawiane automatycznie.

  • Funkcje są po prostu zmiennymi powiązanymi z dowolną liczbą instrukcji Muffin MC .

To ciekawe rozwiązanie wynika z połączenia dwóch naturalnych funkcji Muffin MC :

  1. Makropolecenie Muffin MC I(...) , aby zdefiniować iteratory cykliczne, później używane z formą funkcjonalną #(my-iterator want-number-of-values),

  2. Muffin MC ciąg produktem konstrukt przedłużenie naturalnego zmiennej interpolacji, które ze względu na dowolny łańcuch "F1 F2 F3...", gdzie F i S są albo muffin MC literałami łańcuch lub muffin MC makro polecenia (czyli formy użytkowe) spowoduje tyle napisów jako podane przez kardynał produktu (F1) x kardynał (F2) x ...

Na przykład, biorąc pod uwagę zmienną xa, która przechowuje 2 wartości, mówi aib, oraz y inna zmienna, która przechowuje 3 wartości, mówi 1 2 3, wówczas ocena ciągu "x=$(x) y=$(y))"da 6 różnych wartości, a mianowicie w tej kolejności:

  • „x = ay = 1”
  • „x = ay = 2”
  • „x = ay = 3”
  • „x = przez = 1”
  • „x = przez = 2”
  • „x = przez = 3”

Jest to jedna z najbardziej pożądanych funkcji projektu MUTINY, dla której zaprojektowano Muffin MC .

Uruchom !

#(ascii-art 1)

N


#(ascii-art 3)

N N  
NNN  
N N 


#(map '( #(ascii-art $(_1))) 5 7 9)

N   N
NN  N
N N N
N  NN
N   N

N     N
NN    N
N N   N
N  N  N
N   N N
N    NN
N     N

N       N
NN      N
N N     N
N  N    N
N   N   N
N    N  N
N     N N
N      NN
N       N

Jak to działa

Nasz algorytm opiera się na następujących elementach:

Biorąc pod uwagę wezwanie do ascii-art (n), {n = 2p + 1 | p liczba całkowita, p> = 0}, sztuka do wygenerowania zawiera n ciągów n znaków, z których dwa, najmniejsze i prawe, są stałe i zawsze takie same: „N”. Pozwala to zmniejszyć problem związany z produkcją tylko środkowych strun. Na przykład, biorąc pod uwagę n = 5, chcielibyśmy wyprodukować 5 następujących środkowych łańcuchów, z których każdy składa się z n-2 znaków (dla lepszej wizualizacji zastąpiliśmy spację znakiem „_”):

    The 5 strings :
        _ _ _
        N _ _ 
        _ N _
        _ _ N
        _ _ _

    can be seen as resulting from splitting in groups of 3 characters
    the following infinite sequence of 4 characters :


        /---- < _ _ _ N > ----\
       |                       |
        \---------------------/    


    which, once unfolded, yields the infinite ruban : 

        _ _ _ N _ _ _ N _ _ _ N _ _ _ N _ _ _ N _ _ _ N ...
              ^     ^     ^     ^     
        _ _ _ |     |     |     |
              N _ _ |     |     | 
                    _ N _ |     |
                          _ _ N |
                                _ _ _
  • Takie środkowe struny można łatwo wytworzyć przez cykliczne przewijanie sekwencji 4 elementów ('_' '_' '_' 'N')w 5 grupach po 3; biorąc pod uwagę n, wejście funkcji, taka sekwencja składa się z n-2 znaków '_', po których następuje znak 'N'. Cyklowanie tej sekwencji nie wymaga niczego innego, jak tylko osadzenie sekwencji w wbudowanym iteratorze Muffin MC I(sequence) (iterator, który cyklicznie przewija się przez początkową sekwencję wartości).

  • Następnie produkujemy po prostu środkowe łańcuchy o długości n-2, prosząc naszego iteratora o podanie nam kolejnych wartości n-2 (n - 2 znaków), które są łączone razem w celu uzyskania oczekiwanego środkowego łańcucha.

  • N środkowych łańcuchów powstaje przez powtórzenie n razy powyższego procesu, przy użyciu mapy do zebrania n wyników (n łańcuchów n-2 znaków).

  • Używamy kolejny potężny Muffin MC konstrukt wbudowany, a mianowicie produkt ciąg , aby wyprodukować ostateczny ciągi n: "N#(map...)N".

  • I to wszystko !

    Commented script  
    
    =(ascii-art                    Define the 'ascii-art' variable to hold
                                   the function's definition.
                                   When called, its argument, the actual
                                   value of n, will be bound to the system
                                   variable _1, accessed as $( _1 ).
    
        '(                         '(...) quote macro-command -- protects 
                                   its arguments, here the function 
                                   definition, from being evaluated.
                                   We want to keep it literally for further evaluation.
    
           =(*                     =(*...) // assignment macro-command.
                                   Similar to the Lisp (let (...)...),
                                   not the let* !
    
               x #(2- $(_1))       Define the variable x to hold the value 
                                   n-2.   
    
               I I(                Define I to be an iterator over the 
                                   the x+1 characters sequence :
                    *( $(x) " ")   . x white-space characters
                    N              . 1 'N' character (here the atom N)
                 )
    
               foo '(              Define the variable foo as a function 
                      #(.          to catenate ( #(. s1...) )
                         #(I $(x)) the iterator's next x elements.
                       )            
               )
           )                       End of =(*...
    
        #(say                      Print each element of:
           ?(                      If
              #(== $(_1) 1)        n equals 1
      N                    the atom N,
      "N#(map foo #(.. 1 $(_1)))N" else the n strings as a string-product 
                                   resulting from foo-computing the  
           )                       n middle-strings.
         )
     ))
    

Zadanie 3

Zdefiniuj funkcję gcd():

=(gcd '( ?( #(== $(_2) 0)
        $(_1)
            #(self $(_2) #(mod $(_1) $(_2)))) ))

gcd()„s prawdziwa forma najkrótszy (37 bajtów - 2 bajty zyskują dzięki Rodolvertice)

=(g'(?(#(z$(_2))$(_1)#(g$(_2)#(mod)))))

Uruchom !

#(gcd 225 81)

daje 9.

Otóż ​​to.

Dziękujemy za fajną grę i prawdopodobnie za zainteresowanie. Język jest dostępny dla każdego, kto chciałby się nim bawić, używać go, a nawet rozszerzać. Po prostu poproś o to, a ja chętnie je wyślę.

Twoje zdrowie

Franck


PS. Obecna implementacja Muffin MC znajduje się w Perl5. Kod źródłowy zawiera około 2000 wierszy współczesnego Perla, w tym komentarze, i jest dostarczany wraz z pakietem testowym bez regresji, który świetnie nadaje się do nauki praktycznych konstrukcji Muffin MC i semantyki.


Bardzo miły! Najkrótsza forma ascii-art ma skróconą nazwę funkcji, ale skrót GCD nie. Jest to celowe, ponieważ jeśli nie, możesz ogolić kolejne 2 bajty. +1
rodolphito,

Jasne, i to celowe. Czy powinienem ? tak, zróbmy to;) Dzięki za post i twoje uznanie.
Franck Porcher

1
Ponieważ próbujesz pozbyć się dodatkowych znaków (a ponieważ mogę być niepoprawną gramatycznie nieprzyjemną), możesz (powinieneś) usunąć miejsce przed wykrzyknikiem dla pierwszego zadania. To miejsce jest poprawne po francusku, ale nie po angielsku.
Amos M. Carpenter
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.