Wątek przeniesiony 2021-03-26 21:57 z Ogłoszenia drobne przez cerrato.

Jednolinijkowiec w JS

7

Na mikroblogu pojawił się taki wpis: Pamiętacie, że kiedyś mieliś...

Pamiętacie, że kiedyś mieliśmy tutaj konkurs który polegał na napisaniu najkrótszego programu (w sensie znaków kodu) wyświetlający choinkę? Skojarzyło mi się z zadaniem napisania programu który wyświetla numery od 1 do 100 bez użycia pętli oraz liczb.

Czyli żadne for/next, while, goto itp. Nie można też deklarować cyferek otwartym tekstem jako 123 ani "123".

Wydziergałam pod tym wpisem takie coś:

o=-[]+'';function f(x){console.log(++x);(x<+!!o+o+o)?f(x):o;}f(o);

A później stwierdziłam, że w sumie można krócej:

f=(x)=>{console.log(++x);if(x<'d'.charCodeAt())f(x)};f('')

A później stwierdziłam, że w sumie to można jeszcze krócej:

f=x=>{console.log(++x);if(x<-~o+o+o)f(x)};f(o=~~f+'')

A później podrapałam się po głowie.


I tu pojawia się właściwa treść ogłoszenia:
Jeśli ktoś chce zarobić 100 zł za napisanie jednej linijki w JavaScript, to chętnie zapłacę :) Warunki:

  • skrypt wyświetla liczby od 1 do 100,
  • bez pętli,
  • bez liczb wewnątrz kodu,
  • i oczywiście bez używania zewnętrznych bibliotek,
  • liczba znaków kodu przynajmniej o jeden mniejsza niż w powyższym rozwiązaniu (czyli 52 znaki lub mniej).

Temat jest trochę rozrywkowy, ale ogłoszenie jak najbardziej serio, a stawka wynosi prawie ~2 zł za znak.

Ponieważ zlecenie ma charakter ludyczny, sugeruję, żeby ew. rozwiązania umieszczać po prostu na forum :D

10

udało mi się :) ale kombinowałem trochę. Ale zmieściłem się równo w 52 znakach (może krócej się nie da?):

throw Array.from(Array('d'.charCodeAt()),(_,i)=>++i)
5

Nie wiem czy rozwiązanie @LukeJL jest poprawne ale jeżeli tak to można je skrócić do czegoś takiego

throw Array.from(Array('d'.charCodeAt()).keys()) 

EDIT: Zły przedział

3

Jestem pod wrażeniem :D

Tak się właśnie obawiałam, że jak tu to wrzucę, to znajdą się gieniusie, którzy z gwoździa zrobią mikrofon.

Warunki zadania nie zabraniały wyświetlania na ekranie czegoś więcej niż zadany ciąg, więc rozwiązanie @LukeJL znajduję poprawnym.
Proszę podaj na priv numer konta do przelewu :)

2

A ja mam prośbę do wszystkich, którzy tutaj coś napisali (ze Smoczycą włącznie) - czy możecie wyjaśnić, jak te Wasze hieroglify działają?
Z góry zaznaczam, że płacić za wyjaśnienia nie zamierzam ;)

0
cerrato napisał(a):

Wątek został przeniesiony
15 minut temu
zlecę napisanie jednolinijkowca w JS
Niepoprawna kategoria forum

Ale że co? Przecież to legitne i prawilne ogłoszenie jest :P

6
cerrato napisał(a):

A ja mam prośbę do wszystkich, którzy tutaj coś napisali (ze Smoczycą włącznie) - czy możecie wyjaśnić, jak te Wasze hieroglify działają?

Moje hierogliwy działają tak:

[] - tablica (obiekt)
-[] - tablica skonwertowana na liczbę, daje: -0
-[]+'' - tablica skonwertowana na liczbę, a następnie na string, daje: "0"

.

~f zadeklarowana wcześniej funkcja poddana negacji bitowej daje: -1
~~f poddana podwójnej negacji bitowej daje: 0
~~f+'' - zmiana typu do stringa: "0"

.

!o - zaprzeczone "0" daje: false
!!o - podwójnie zaprzeczone "0" daje: true
+!!o - podwójnie zaprzeczone "0", konwertowane na liczbę daje: 1

.

~o - "0" poddane negacji bitowej daje -1
-~o - "0" poddane negacji bitowej i zmianie znaku daje 1

.

+!!o+o+o czyli to samo co: 1 +"0" + "0" daje: "100"

5
cerrato napisał(a):

A ja mam prośbę do wszystkich, którzy tutaj coś napisali (ze Smoczycą włącznie) - czy możecie wyjaśnić, jak te Wasze hieroglify działają?

throw Array.from(Array('d'.charCodeAt()),(_,i)=>++i)
'd'.charCodeAt() // zwraca kod ascii znaku d == 100
Array(100) // tworzy tablice z liczba elementów 100
Array.from(arrLike, func) // tworzy tablice z elementu iterowalnego lub podobnego do tablicy i może przyjąć jako argument funkcje do mapowania
Array.from(arrLike).map((v, x)=> ++x) // mała sztuczka bo
 Array.from(arrLike).map((x)=> ++x)  // zwróci tablice pełną NaN'ów
// pierwszy argument (v) to wartość (który przy Array(n) będzie równa 'undefined') za to drugi (x) to indeks więc każdy element będzie miał wartość swój indeks + 1
Array.from(Array('d'.charCodeAt()).keys()) 
Array('d'.charCodeAt()).keys() // zwraca iterator nowoutworzonej tablicy  za to
Array.from() // tworzy tablice z elementu iterowalnego lub podobnego do tablicy (Chociaż chwile mi zajęło przypomnienie jak działa cały kod)

Array.from() spec

4

To jako ciekawostkę dorzucę szachy... w ~1000 bajtach.
https://nanochess.org/archive/toledo_javascript_chess_3.html
https://nanochess.org/chess4.html

<script>//(c)2009 Oscar Toledo G.
var B,i,y,u,b,I=[],G=120,x=10,z=15,M=1e4,l=[5,3,4,6,2,4,3,5,1,1,1,1,1,1,1,1,9,9
,9,9,9,9,9,9,13,11,12,14,10,12,11,13,0,99,0,306,297,495,846,-1,0,1,2,2,1,0,-1,-
1,1,-10,10,-11,-9,9,11,10,20,-9,-11,-10,-20,-21,-19,-12,-8,8,12,19,21];function
X(w,c,h,e,S,s){var t,o,L,E,d,O=e,N=-M*M,K=78-h<<x,p,g,n,m,A,q,r,C,J,a=y?-x:x;
y^=8;G++;d=w||s&&s>=h&&X(0,0,0,21,0,0)>M;do{if(o=I[p=O]){q=o&z^y;if(q<7){A=q--&
2?8:4;C=o-9&z?[53,47,61,51,47,47][q]:57;do{r=I[p+=l[C]];if(!w|p==w){g=q|p+a-S?0
:S;if(!r&(!!q|A<3||!!g)||(r+1&z^y)>9&&q|A>2){if(m=!(r-2&7))return y^=8,I[G--]=
O,K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);while(n<=t){L=r?l[r&7|32]-h-q:0;if(
s)L+=(1-q?l[(p-p%x)/x+37]-l[(O-O%x)/x+37]+l[p%x+38]*(q?1:2)-l[O%x+38]+(o&16)/2:
!!m*9)+(!q?!(I[p-1]^n)+!(I[p+1]^n)+l[n&7|32]-99+!!g*99+(A<2):0)+!(E^y^9);if(s>h
||1<s&s==h&&L>z|d){I[p]=n,I[O]=m?(I[g]=I[m],I[m]=0):g?I[g]=0:0;L-=X(s>h|d?0:p,L
-N,h+1,I[G+1],J=q|A>1?0:p,s);if(!(h||s-1|B-O|i-n|p-b|L<-M))return W(),G--,u=J;
J=q-1|A<7||m||!s|d|r|o<z||X(0,0,0,21,0,0)>M;I[O]=o;I[p]=r;m?(I[m]=I[g],I[g]=0):
g?I[g]=9^y:0;}if(L>N||s>1&&L==N&&!h&&Math.random()<.5){I[G]=O;if(s>1){if(h&&c-L
<0)return y^=8,G--,L;if(!h)i=n,B=O,b=p;}N=L;}n+=J||(g=p,m=p<O?g-3:g+2,I[m]<z|I[
m+O-p]||I[p+=p-O])?1:0;}}}}while(!r&q>2||(p=O,q|A>2|o>z&!r&&++C*--A));}}}while(
++O>98?O=20:e-O);return y^=8,G--,N+M*M&&N>-K+1924|d?N:0;}B=i=y=u=0;while(B++<
120)I[B-1]=B%x?B/x%x<2|B%x<2?7:B/x&4?0:l[i++]|16:7;for(a=
"<table cellspacing=0 align=center>",i=18;i<100;a+=++i%10-9?
"<th width=40 height=40 onclick=Y("+i+") style='border:2px solid #aae' id=o"+i+
" bgcolor=#"+(i*.9&1?"9090d0>":"c0c0ff>"):(i++,"<tr>"));
a+="<th colspan=8><select id=t><option>Q<option>R<option>B";
document.write(a+"<option>N</select></table>");
function W(){B=b;for(p=21;p<99;++p)if(q=document.getElementById("o"+p)){q.
innerHTML="<img width=40 src="+(I[p]&z)+".gif>";q.
style.borderColor=p==B?"#ff0":"#aae";}}W();
function Y(s){i=(I[s]^y)&z;if(i>8){b=s;W();}else if(B&&i<9){b=s;i=I[B]&z;if((i&
7)==1&(b<29|b>90))i=14-document.getElementById("t").selectedIndex^y;X(0,0,0,21,
u,1);if(y)setTimeout("X(0,0,0,21,u,2/*ply*/),X(0,0,0,21,u,1)",250);}}
</script>
4

A może coś ciekawszego? ;) https://www.dwitter.net pokażcie co umiecie namalować w 140 znakach

2

To rozwiązanie nie jest może najkrótsze, bo kod liczy aż 100 znaków, ale podoba mi się idea:

<script>
//:)
f = (x) => {console.log (++x);
  if (x<=document.currentScript.text.length) f(x);
};
f ('');
</script>
3
f=x=>--x?[f(x),x].flat():[];throw f(-~f+''+~~f+-~f)
3

Mnie się tak udało w 48 znakach, ale łamię zasady: (1) liczy od 100 do 1, (2) dopisuje 0 na końcu. I czy nie w nowych liniach się w ogóle liczy? Można dopisać \n, ale to już będzie 50 znaków… W każdym razie zamieszczam, coby mi nie zginęło. Może da się jeszcze usprawnić.

x=+!"";(f=y=>y&&`${y}`+f(--y))((++x*++x<<++x)+x)

UPDATE: Skrócone dzięki motywacji ze strony @Freja Draco – 47 znaków (bez nowych linii). Zamieniłem ciąg <tu backtick>${y}<tu backtick> na ""+y (kurczę, nie mogę dojść z Markdownem, wciąż nie udaje się zapisać backticka):

x=+!"";(f=y=>y&&""+y+f(--y))((++x*++x<<++x)+x)

UPDATE2: Zmodyfikowane przez @m94 – 38 znaków (bez nowych linii, ale ze spacjami) (PS2 Aha, i liczy od 1 do 100 :) ):

(f=y=>y&&f(--y)+" "+y)(-~f+''+~~f+-~f)

UPDATE3: Tyle samo znaków, ale bez dodatkowego zera (teraz jest tylko jedno zero, przedtem były dwa):

(f=y=>--y&&f(y)+" "+y)(-~f+''+~~f+-~f)

UPDATE4: Zastanowiło mnie, czemu przeniesienie dekrementacji powoduje wyświetlanie o jedno zero mniej. Wyjaśnienie, jak ja to widzę (mam nadzieję, że nie pomyliłem się!):

Dla kodu (f=y=>y&&f(--y)+" "+y)(-~f+''+~~f+-~f):

  1. 101 && f(100) (wywołanie nr 1, zapamiętane y jest 100)
  2. 100 && f(99) (wywołanie nr 2, zapamiętane y jest 99)
  3. 2 && f(1) (wywołanie nr 100, zapamiętane y jest 1)
  4. 1 && f(0) (wywołanie nr 101, zapamiętane y jest 0)
  5. 0 (wywołanie nr 102, nic nie jest już zapamiętywane)

Następnie powrót:

  1. Powrót do wywołania nr 101: 0 + " " + 0
  2. Powrót do wywołania nr 100: "0 0" + " " + 1

Są dwa zera.

Dla kodu (f=y=>--y&&f(y)+" "+y)(-~f+''+~~f+-~f) (dekrementacja przeniesiona):

  1. 100 && f(100) (wywołanie nr 1, zapamiętane y jest 100)
  2. 99 && f(99) (wywołanie nr 2, zapamiętane y jest 99)
  3. 1 && f(1) (wywołanie nr 100, zapamiętane y jest 1)
  4. 0 (wywołanie nr 101, nic nie jest już zapamiętywane)

Następnie powrót:

  1. Powrót do wywołania nr 100: 0 + " " + 1

Jest jedno zero. Jej… Nadal nie wiem, czemu nie dwa.


PS Chyba już wiem. W pierwszym kodzie zapamiętane jest dodatkowe zero, bo warunek y && ... nic nie wie o dekrementacji. Jakoś tak. Muszę jeszcze pouczyć się rekurencji…


UPDATE5: Udało mi się usunąć dwa początkowe zera, ale kod jest dłuższy (49 znaków) i ma wciąż spację na początku:

(f=y=>(--y&&f(y)||"")+" "+(y-~f))(-~f+''+~~f+~~f)
1

Jakby ktoś chciał napisać taki sam program, ale w Bashu, to tutaj założyłem wątek z wyzwaniem -> Jednolinijkowiec w Bashu – liczby od 1 do 100 :)

5

Wypłata poszła właśnie do pierwszej osoby, która zrealizowała zlecenie: LukeJL-a.
Nadal nie rozumiem, dlaczego Cerrato usunął ten wątek z działu ogłoszeń :p

Wszystkim, pozostałym którzy udzielali się w wątku i wyprodukowali rozwiązania przyprawiające mnie o ból mózgu serdecznie dziękuję :)

4

Takiego jeszcze rozwiązania nie było:

throw Array(+atob('MTAw')).fill().map((_,i)=>++i)

throw[...Array(+atob('MTAw'))].map((_,i)=>++i)
0
gk1982 napisał(a):

Takiego jeszcze rozwiązania nie było

A możesz je wytłumaczyć?

4

inne i proste podejście - 39 znaków

(f=i=>i[o+o]?i:i+' '+f(++i+''))(o=+!'')

najpierw przypisujemy

o=+!'' czyli 1
potem wywołujemy funkcję
i=>i[o+o]?i:i+' '+f(++i+'') z argumentem 1
w przypadku gdy na trzecim miejscu (o+o) mamy truthy value to zwracamy "i" (to będzie prawdziwe tylko dla wartości trzycyfrowej - "100"), w przeciwnym wypadku i+' '+f(++i+'') - czyli zwracamy i, postinkrementujemy i i dodajemy wartość funkcji dla zwiększonego o 1 i zamieniamy na stringa (tak żeby dało się sprawdzić wartość na trzeciej pozycji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1