Kendi kaynak kodunu işleyen bir "hacker typer" programı oluşturun


25

Hacker Typer'ı bilmiyorsanız, bkz. Hackertyper.net . Kısacası, komedi etkisi için tuş vuruşu başına bir kod tabanının bir yığınını veren bir programdır. AMA, hackertyper.net versiyonunu uygulamak çok kolaydır. İsteğe bağlı bir kod parçasından bir defada üç karakter çıkarır . Bu zorluk için, bir program kendi kaynak kodunu çıkarmalı ve her tuş basışında bir boşlukla ayrılmış kod parçası yazdırmalıdır .

ayrıntılar

  • Bir program için bir dosya adını zor kodlayamaz; adını dinamik olarak belirlemelidir. Program çalıştırılabilir bir dosyaya derlenirse, standart dosya uzantısını çalıştırılabilir dosya adına ekler (Windows kullanıyorsanız .exe hariç) ve kaynak dosyanın çalıştırılabilir dizinde olduğunu varsayabilir. Örneğin, bir C çalıştırıcısı "hacker" olarak adlandırılmışsa, kaynak kodunu aynı dizinde "hacker.c" adlı bir dosyadan alması gerekir. Derlenmiş bir programın bir uzantısı varsa, kaynak kodunun adını ("typer.exe" -> "typer.cs") belirlemeden önce bırakılmalıdır.
  • Programlar, her alan arasında en az bir karakter olacak şekilde en az 5 boşluk içermelidir. Bu, bu meydan okuma için mümkün olan en küçük boyut 9 bayttır anlamına gelir. Boşlukların programın çalışması için çok önemli olması şart değildir.
  • Çıktıda her türlü biçimlendirme (girintiler, yeni çizgiler vb.) Korunmalıdır. Bu biçimlendirme, onu biçimlendiren kodla basılabilir veya onu izler, önemli olan biçimlendirmenin sürdürülmesidir.
  • Seçtiğiniz dilde boşlukları uygulamak için başka bir yol yoksa, 5 boşluk gereksinimini karşılamak için yorum kullanmaktan kaçının.

EDIT : Yeni çizgiler, boşluk ayırıcı olarak veya yerine boşluk olarak kullanılabilir.


1
Biraz kafam karıştı. Program kısa mı olmalı yoksa olmaz mı?
Orby

8
Açıkladığınız şekilde, kodu orijinal kaynak dosyadan okumak için uygun olmaz gibi ses çıkarır. Programın asıl bir olmanın olmasının daha iyi bir yarışma olacağını düşünüyorum.
Orby

1
@Orby Programın, kaynağın okunmasına izin verilip verilmediğine bakılmaksızın, geleneksel anlamda bir kuyruk olmadığını söyleyebilirim. Quines'in girişi yok ama bu programlar açıkça var.
Calvin'in Hobileri

@DrJPepper Üçüncü madde işaret noktanız, herhangi bir beyaz boşluk dizisinin sınırlayıcı olarak sayıldığı gibi ses çıkarır ancak özellikle yalnızca boşluk olduğunu söylersiniz. Açıklayabilir misin?
Calvin'in Hobileri

2
Bu zorluk, programın kendi kaynak kodunun okunmasını teşvik eder; bu, tipik olarak maden yapımında bir pratiktir.
feersum

Yanıtlar:


13

bash, 51 58

for w in $(<$0);do read -sn 1;printf -- "$w ";done

2
2: read: Illegal option -s
Fena

1
Bash cat $0$(<$0)

geribildirim için @broslow thx; etiketli bash, aynı uzunlukta
Will

1
@ Sorun yok. IFS=\ Shebang'ı atlarsan , gerçekten gerekli mi? Varsayılan IFS gibi bir şey IFS=$'\n\t 've artık yeni bir hattınız olmadığından, onu yalnızca boşluklarla sınırlamanız gerektiğini düşünmüyorum.

1
for w in `<$0`;{ read \-sn1;printf $w\ ;}
jimmy23013

21

HTML ve JavaScript, 123

<head></head><body onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[2].textContent += s.split(/(?= )/)[i++%6]"></body>

Bu, hacker typer'a benzer şekilde çalışır, ancak kendi kaynak koduyla. Kuralları yanlış anladıysam bana haber ver.

Ve işte tarz bir versiyon (170 karakter):

<head></head>
<body style="background:#000;color:lime" onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[3].textContent+=s.split(/(?=\s)/)[i++%6]">
<pre></pre></body>

Bir demo yaptım . JS Bin çok fazladan ekstra kod eklediği için değiştirildi, ancak genel fikir aynı.


2
<html> ve <head> etiketleri olmadan ve bir kapanış </body> olmadan doğru şekilde sonuç vermezse şaşırırdım. Bu konuda tüm tarayıcıların ne kadar bağışlayıcı olduğunu görünce şaşıracaksınız.
Will

2
@ Will Teşekkürler. Dahil etmemin sebebi <head>, orada değilse tarayıcının ekleyeceği, böylece her zaman görüntüleneceği idi. <html>Yine de unuttum .
grc

12

Perl + Terim :: ReadKey, 56 bayt

use
Term'ReadKey;ReadMode
4;open
0;ReadKey,print
for
<0>

Sayesinde ThisSuitIsBlackNot orijinal ilham ve karşı primo öneren open 0ve <0>.

Sonrasındaki yeni satırın forgerçekten gereksiz olduğuna dikkat edin , ancak boşlukların belirtilen minimum beşe kadar sayılmasını sağlamak için bir yere fazladan bir yeni satır eklemem gerekiyor .

Ayrıca, ThisSuitIsBlackNot'un gönderiminde olduğu gibi, bu programın da CPAN'dan Term :: ReadKey modülünü gerektirdiğini unutmayın . Debian / Ubuntu Linux'ta bu modül henüz mevcut değilse, komut ile kolayca kurulabilir sudo apt-get install libterm-readkey-perl.

Ayrıca, birkaç karakter kaydetmek için bu program giriş modunu çıkışta normale döndürmez, bu nedenle kendinizi yazdıktan sonra ne yazdığınızı göremeyebilirsiniz. Shell komutunu çalıştırıyorsanız stty saneya da resetdüzeltmelisiniz. Bu sorun, 10 ekstra bayt pahasına, aşağıdakilerle giderilebilir:

use
Term'ReadKey;ReadMode
4;open
0;ReadKey,print
for<0>;ReadMode
0

Bonus: Saf yüzgeç, 81 bayt

$_=q{use
Term'ReadKey;ReadMode
4;ReadKey,say
for
split$/,
"\$_=q{$_};eval"};eval

Yine, virgülden sonraki yeni satır sadece minimum beş boşlukla buluşmak için gerekli.

Yukarıdaki 56 baytlık programdan farklı olarak, bu sürüm aslında kendi kaynak kodunu okumak zorunda değildir, çünkü bir yazıya, özellikle de bu yazıya dayanır:

$_=q{say"\$_=q{$_};eval"};eval

Bu quine hakkında güzel bir şey q{ }, tekrarlamak zorunda kalmadan kolayca bir "yükü" kolayca taşıyabiliyor olmasıdır. Kısacası oldukça <0>yenemezken, oldukça yaklaşıyor.

Not: Bu program Perl 5.10+ sayözelliğini kullanır ve bu nedenle -M5.010(veya -E) komut satırı anahtarı ile başlatılması gerekir . Meta üzerine kurulan fikir birliğine göre, modern dil özelliklerini etkinleştirmek için kullanılan bu tür anahtarlar fazladan karakter sayılmaz . Olmadan bulabildiğim en kısa çözüm say83 bayttır:

$_=q{use
Term'ReadKey;ReadMode
4;ReadKey,print
for
split/^/,
"\$_=q{$_};eval"};eval

Bunların her ikisi de (son iki satıra katılarak) yerleştirerek daha terminal dostu hale getirilebilir:

;ReadMode
0

sondan önce }.


Vay. Sadece vay canına. Çok havalı.
ThisSuitIsBlackNot 6:14

+1, ancak stty sanebunun yerine yazma alışkanlığı olmasını öneririm reset(bazı os'ta bazen bazı terminal parametrelerini sıfırlamaktan daha fazlasını yapabilir) ^^
Olivier Dulac

Çok güzel bir çözüm. FWIW, open F,$0ve <F>ile değiştirilebilir open 0ve <0>. Ayrıca, metadaki bir gönderinin gerçekten bir fikir birliği teşkil etmediğini savunuyorum. Bu seçenek -M5.01, "dilin belirli bir noktaya getirilmesi" anlamına gelmez , yazarın önerdiği gibi özellikleri etkinleştirir. Bu özelliklerin varsayılan olarak etkin olduğu bir perl sürümü yoktur.
primo

3
@primo: Mevcut cevaba katılmıyorsanız, lütfen meta cevabına kendi cevabınızı yazınız. Şu ana kadar kimsenin üç buçuk yıl içinde yapılmadığı gerçeği, en azından burada aktif olarak meta ziyaret eden normaller arasında makul bir fikir birliği önermektedir, ancak fikir birliği her zaman değişebilir. (Her neyse, gördüğüm gibi, ruby golfscript.rb foo.gsGolfScript ile yazılmış bir programı çalıştırmak için geçerli bir komut olarak sayılıyorsa, o zaman perl -M5.010 foo.pl"Perl 5.10" ile yazılmış bir programı çalıştırmak için geçerli bir komut olarak sayılmalıdır . burada.)
Ilmari Karonen

5

Python 3 - 124 bayt - 7 boşluk


Kod:

from curses import*
s=initscr();noecho()
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ")
echo();endwin()

Ungolfed:

from curses import*
# init curses
screen=initscr()
noecho()
# split code into spaces
code = open(__file__).read().split(" ")
for x in code:
    # wait for keypress
    screen.getch()
    # print a bit
    screen.addstr(x+" ")
# deactivate curses
echo()
endwin()

Tarz sürümü:

from curses import*
s=initscr();noecho();start_color();init_pair(2,COLOR_GREEN,COLOR_BLACK)
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ",color_pair(2))
echo();endwin()

4

Ruby, 85 , 71

require"io/console";f=File.open __FILE__;loop{STDIN.raw &:getc;print f.read(3)||exit}

IO#rawStandart kütüphanenin bir parçası olmaması çok kötü .

Gelişme iyilesme duzelme ilerleme

require"io/console";24.times{|q|STDIN.raw &:getc;$><<IO.read($0,3,q*3)}

Bu, Çekirdek # çıkış çağrısını ortadan kaldırır ve kodu kısaltmak için genel değişkenleri kullanır.


4

Befunge - 21

~ $ g , 1 +:54*`#@_:0

Befunge'yi yeni öğrendim, bundan oldukça memnunum. Bir açılır pencereye "yazmaktan sakıncası yoksa, daha iyi bir çevrimiçi tercüman bulana kadar burada veya burada çalıştırabilirsiniz .


2

Powershell, 89

(gc $MyInvocation.MyCommand.Path).split(" ")|%{$l+="$_ ";write-host "$l";read-host ;cls}

2

Python 3 - 299

a="""from curses import*
s=initscr()
raw()
noecho()
for x in e:
 s.getch()
 s.addstr(x+' ')
nocbreak()
echo()
endwin()
""";b="""e=(a+'a=#%s#;b=#%s#;%s'%(a,b,b.replace('#','""''"',4))+'exec(a)').split(' ')
""";e=('a="""%s""";b="""%s""";%s'%(a,b,b.replace('#','""''"',4))+'exec(a)').split(' ')
exec(a)

Onun bir sırtı. 507'den execbazı ifadeleri kullanarak ve hareket ettirerek kısaltıldı .


2

C, 211 186 bayt

C'deki çözümüm curses kütüphanesini kullanıyor. Diğer C çözeltisinden daha uzun olabilir, ancak bir kıskaç. Sorunun gerektirmediği halde, yine de oldukça hoş. Aynı zamanda oldukça iyi çalışıyor:

#define R(x)#x
#define T(x)R(x)
#define S(p)char*s="#define R(x)#x\n#define T(x)R(x)\n#define S(p)"p"\nS(T(S(p)))";main(){initscr();noecho();while(*s)if(~getch())addch(*s++);}
S(T(S(p)))

Bazı yorumlar ve sayfalarla birlikte daha okunaklı bir sürüm:

#define R(x)#x /* macros to convert the source code in S into a C-string */
#define T(x)R(x)
#define S(p) char*s="#define R(x)#x\n" \
                    "#define T(x)R(x)\n" \
                    "#define S(p) " p "\n" \
                    "S(T(S(p)))";\
    main(){\
        initscr();\
        noecho(); /* don't echo input */ \
        while(*s)\
            if(~getch()) /*true if character has been typed */ \
                addch(*s++);\
}
S(T(S(p)))

ile derlemek:

gcc -o h h.c -lncurses

2

C - 136 135 132 bayt (yalnızca Windows)

*fopen();**v;b[ 1<<20];main(p,q){v=q; strcpy(b,*v);strcat(b,".c") ;for(*v=fopen(b,"r");~fscanf(*v,"%s",b);printf("%s ",b))getch();} 

Not: Programın sonunda muhtemelen görünmeyecek bir boşluk var.

Bu programın, kendimden başka bir bilgisayar üzerinde çalışacağını garanti edemiyorum, çünkü oldukça hack. Herkes sadece 32-bit makinelere sahip olduğunda işler çok daha kolay olurdu. Daha sonra sizeof(int*)8 yaşımda endişelenmeme gerek kalmayacak (ki kesinlikle öyle; emin olmak için yazdırdım) 4'ken sizeof(int).

Ne mutlu ki, çalıştırılabilir dosyanın adı argv'deki ilk dizgide saklanır. Ancak, bir işaretçiyi bir işleve argüman olarak koymak, işlevin argümanlarının türünü açıkça belirtmem gerektiği anlamına gelir - yani intiki kez yazmam gerekeceği anlamına gelir - büyük bir karakter kaybı. Neyse ki bir geçici çözüm buldum. Main için ikinci tartışmam vardı, qbaşka bir int ol. Sonra qbir çeşit değişken atama bir int**şekilde tüm gerekli baytları yığından tutmayı başardı.

fopenFonksiyonu bildirmeden dönüş türünü bir işaretçi olarak yorumlamak için bu tür püf noktaları bulmakta başarısız oldum .

Düzenleme: fark ettim ~fscanf(*v,"%s",b)yerine kullanmalıyımfscanf(*v,"%s",b)>0 EOF ulaşıldığında -1 döndürdüğünden .


Bu benim için segfaults bu yüzden test edemiyorum, ancak void **v;prototip yerine bir void pointer ( ) tanımlayabilmelisiniz fopen().
Komintern

@Comintern bu değişikliğin sonucunu doğru şekilde kaydetmeme yardımcı olmadı fopen. İnt için boşluk bırakmanın neden bir fark yaratması gerektiğini anlamıyorum, çünkü tüm işaretçiler aynı boyutta.
feersum

İyi bir nokta. Gerçi hala daha kısa ve daha istikrarlı bir işaretçi bildirmek - Bu aslında benim için çalıştırır: b[1<<20];main(int *c,char **v){strcpy(b,*v);strcat(b,".c");c=fopen(b,"r");for(;fscanf(c,"%s",b)>0;printf("%s ",b))getch();}(ı yerine zorunda getchar()için getch()gerçi).
Komintern

@Comintern kodunuz hala sistemimde çöküyor, ancak işe yaraması iyi bir iş. Dediğim gibi sanırım - programın her sürümü 1 bilgisayarda çalışacak.
feersum

Neden K&R prototiplerini kullanmıyorsunuz? Örneğin *fopen()yerine *fopen(a,b)?
FUZxxl

1

Perl - 87 bayt

#!/usr/bin/perl -040
use Term::ReadKey;open F,$0;ReadMode 3;print''.<F>while ReadKey 0

Dosya sonuna kadar okunduktan sonra ne yapılması gerektiğiyle ilgili kurallarda hiçbir şey görmedim, bu yüzden son parça yazdırdıktan sonra girişi beklemek yeterli.


1

LiveScript ile node.js:

#!/usr/local/bin/lsc
console.log <| require \fs .readFileSync __filename, encoding: \utf8

zaman uyumsuz sürüm:

#!/usr/local/bin/lsc
require \fs .readFile __filename, encoding: \utf8, -> console.log &1

1

Kobra - 147

class P
    def main
        while 1,for a in File.readLines(CobraCore.exePath[:-4]+'.cobra'),print if('[Console.readKey]'and (Console.cursorLeft=0)<1,a,'')*

CobraCore.exePath çok kullanışlı!


1

Javascript ES6, 154

Firefox 154 :

(a= (i=1,b="(a= "+a+")()",s="") => {window.onkeydown=()=>{clear();i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);console.log(s+d);if(i<0){i=0,s+=d}}})()

Chrome 175 :

( a= function (i,s){b="( a= "+a+")()";c=console,window.onkeydown=function(){c.clear();s=s||"",i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);c.log(s+d);if(i<0){i=0,s+=d}}})()

Her ikisi de 274 :

( a= function (i,s){b="( a= "+a+")()";c=console,window.onkeydown=function(){(clear)?clear():c.clear?c.clear():0;s=s||"",i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);c.log(s+d);if(i<0){i=0,s+=d}}})()

Ungolfed (krom):

( a= function (i,s){        // starting index | undefined, output string
    b="( a= "+a+")()";      // get a string representation of the function
    c=console,
    window.onkeydown=function(){    // on each key down event
        c.clear();                  // clear the output 
        s=s||"";
        i=b.indexOf(" ",i+1);       // get the index of next space
        d=b.slice(0,i<0?b.length:i);// get the string part wanted
        c.log(s+d);                 // print the string
        if(i<0){
            i=0,                    // reset counters
            s+=d                    // adding the string to the main output
        }
    }
})()

İki sürümü vardır, çünkü Chrome ok işlevini işlemez ve konsol aynı yöntemle silinmez

Firefox one firebug ile çalışır, görünüşe göre geliştirici konsolu bir betikten silinemez.


Çıktıyı yazdırmak için kullanıcının rasgele tuşlara basması gerekliliğini mi kaçırdınız?
Doktor

Elbette, bunu tekrar yazacağım.
Hacketo

0

Harika - 379

import java.nio.file.*
Path p = Paths.get(System.getProperty("user.dir"))
DirectoryStream<Path> f = Files.newDirectoryStream(p,"*.groovy")
try{for(e in f){read(e.toAbsolutePath().toString())}}
catch(Exception e){ }
finally{f.close()}

void read(String x){
    def s = new File(x).text
    for(e in s.replace("%n"," %n").split(" ")) 
        print e + " " 
    Thread.sleep(200)
}   

getch()Java ve Java esque dillerinde Groovy gibi hiçbir eşdeğeri olmadığından ... temelde kodum tuşlara basmıyor. Hepsi bu kadar: D


0

C, 248 karakter

Gerçek quine

Yalnızca unix'te çalışır, pencerelerde _getch kullanılarak uygulanır.

main(){char *p="main(){char *p=\"%s\",s[400];sprintf(s,p,p);system(\"stty raw\");for(p=s;*p!=0;putchar(*p++))getchar();system(\"stty cooked\");}",s[400];sprintf(s,p,p);system("stty raw");for(p=s;*p!=0;putchar(*p++))getchar();system("stty cooked");}

0

HTML ve Javascript, 232 bayt

<body><script>var n=0;var f=function (){document.onkeypress=function(){document.body.innerHTML+=("&lt;body>&lt;script>var n=0;var f="+f.toString()+"f()&lt;/script>&lt;/body>").split(" ")[n]+" ";n++;}};f()</script></body>

Geleneksel Javascript quine, ancak değiştirilmiş.

JSFiddle burada .


0

SmileBASIC, 79 75 bayt

LOAD"PRG1:"+PRGNAME$()
PRGEDIT 1
@L
IF BUTTON(2)THEN?PRGGET$();
WAIT
GOTO@L

SmileBASIC'te bir programın belirli bir HATINI elde etmek çok kolaydır, bu yüzden her satırı kesmeden önce boşluk bıraktım.Her zekice ara vermeden önce boşlukları bırakarak çok zekiyim sanıyordum, ama görünüşe göre boşluk yerine satır kesmeleri kullanmamıza izin veriyor ...

Açıklama:

LOAD "PRG1:"+PRGNAME$() 'load the code into slot 1 so we can easily read 1 line at a time
PRGEDIT 1 'Edit slot 1
@LOOP
IF BUTTON(2) THEN 'When a button is pressed...
                   PRINT PRGGET$(); 'get a line of code and print it
WAIT 'delay so we don't detect the same press multiple times in a single frame.
GOTO @LOOP 

-1

Haskell

{-# LANGUAGE CPP #-}
main = readFile __FILE__ >>= putStrLn

Bu sadece kaynağını yazdırır.
Carcigenicate
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.