Tạo một chương trình tin tặc của người dùng tin tặc


25

Nếu bạn không quen thuộc với hacker typer, hãy xem hackertyper.net . Nói tóm lại, đây là một chương trình xuất ra một đoạn cơ sở mã cho mỗi lần nhấn phím để tạo hiệu ứng hài. NHƯNG, phiên bản hackertyper.net quá dễ thực hiện. Nó chỉ đơn giản là xuất ba ký tự cùng một lúc từ một đoạn mã tùy ý . Đối với thử thách này, một chương trình phải xuất mã nguồn riêng của mình và in một đoạn mã được phân tách bằng dấu cách cho mỗi lần nhấn phím.

Chi tiết

  • Người ta không thể mã cứng tên tệp cho chương trình; nó phải xác định tên của nó một cách linh hoạt. Nếu chương trình biên dịch thành tệp thực thi, nó có thể nối phần mở rộng tệp tiêu chuẩn vào tên của tệp thực thi (không bao gồm .exe nếu sử dụng Windows) và giả sử rằng tệp nguồn nằm trong thư mục của tệp thực thi. Ví dụ: nếu một tệp thực thi C được đặt tên là "hacker", thì nó sẽ lấy mã nguồn của nó từ một tệp có tên "hacker.c" trong cùng thư mục của nó. Nếu một chương trình được biên dịch có phần mở rộng, thì nên bỏ nó trước khi xác định tên của mã nguồn của nó ("typer.exe" -> "typer.cs").
  • Các chương trình phải chứa ít nhất 5 khoảng trắng, với ít nhất một ký tự giữa mỗi khoảng trắng. Điều này có nghĩa là kích thước nhỏ nhất có thể cho thử thách này là 9 byte. Các không gian không phải là rất quan trọng đối với chức năng của chương trình.
  • Mọi định dạng (thụt đầu dòng, dòng mới, v.v.) phải được duy trì trong đầu ra. Định dạng này có thể được in bằng mã tiến hành hoặc theo mã, điều quan trọng là định dạng được duy trì.
  • Tránh sử dụng các nhận xét để đáp ứng 5 yêu cầu không gian trừ khi không có cách nào khác để thực hiện các khoảng trắng trong ngôn ngữ bạn chọn.

EDIT : Các dòng mới có thể được sử dụng thay thế hoặc ngoài các khoảng trắng làm dấu phân cách khối.


1
Tôi có chút bối rối. Chương trình có nên là một quine, hay không?
Orby

8
Cách bạn mô tả nó làm cho nó có vẻ như có thể chấp nhận được để đọc mã từ tệp nguồn gốc, đây sẽ không phải là một vấn đề. Tôi nghĩ rằng nó sẽ là một cuộc thi tốt hơn nếu chương trình phải là một cuộc thi thực sự.
Orby

1
@Orby Tôi muốn nói rằng chương trình không phải là một câu hỏi theo nghĩa truyền thống, bất kể việc đọc nguồn có được phép hay không. Quines không có đầu vào nhưng những chương trình này rõ ràng làm.
Sở thích của Calvin

@DrJPepper Dấu đầu dòng thứ ba của bạn làm cho âm thanh giống như bất kỳ chuỗi khoảng trắng nào được tính là dấu phân cách nhưng bạn đặc biệt nói rằng chỉ có không gian. Bạn có thể làm rõ?
Sở thích của Calvin

2
Thử thách này khuyến khích việc đọc mã nguồn riêng của chương trình, một cách thực hành điển hình trong việc xây dựng các câu hỏi.
frageum

Câu trả lời:


13

bash, 51 58

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

2
Đó là bash, không phải shell: Điều này sẽ không hoạt động dưới dấu gạch ngang, ( 2: read: Illegal option -s)
F. Hauri

1
Giả sử bash, có thể thay thế cat $0$(<$0)

@broslow thx cho phản hồi; bash có nhãn, cùng chiều dài
Sẽ

1
@ Sẽ không có vấn đề gì. Là IFS=\ thực sự cần thiết nếu bạn bỏ qua shebang? IFS mặc định là một cái gì đó giống như IFS=$'\n\t ', và vì bạn không còn có một dòng mới, tôi không nghĩ bạn cần giới hạn nó chỉ trong không gian.

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

21

HTML & JavaScript, 123

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

Điều này hoạt động tương tự như typer hacker, nhưng với mã nguồn riêng của nó. Hãy cho tôi biết nếu tôi hiểu sai các quy tắc.

Và đây là phiên bản theo kiểu (170 ký tự):

<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>

Tôi đã làm một bản demo . Nó đã được sửa đổi vì JS Bin thêm rất nhiều mã bổ sung, nhưng ý tưởng chung là như nhau.


2
Tôi sẽ ngạc nhiên nếu điều này không hiển thị chính xác nếu không có thẻ <html> và <head> và không có đóng </ body>. Bạn sẽ ngạc nhiên về việc rất tha thứ cho tất cả các trình duyệt về vấn đề này.
Sẽ

2
@ Sẽ cảm ơn. Lý do tôi đưa vào <head>là trình duyệt sẽ thêm nó nếu nó không ở đó, vì vậy nó sẽ luôn được hiển thị. Tôi quên mất <html>mặc dù.
grc

12

Perl + Term :: ReadKey, 56 byte

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

Cảm ơn ThisSuitIsBlackNot cho cảm hứng ban đầu, và để mồi cho gợi ý open 0<0>.

Lưu ý rằng dòng mới sau đó forthực sự không cần thiết, ngoại trừ việc tôi cần bao gồm một dòng mới bổ sung ở đâu đó để đưa số lượng khoảng trắng lên đến mức tối thiểu được chỉ định là năm.

Cũng lưu ý rằng, giống như đệ trình của ThisSuitIsBlackNot, chương trình này yêu cầu mô đun Term :: ReadKey từ CPAN. Trên Debian / Ubuntu Linux, mô-đun này, nếu chưa có, có thể dễ dàng cài đặt bằng lệnh sudo apt-get install libterm-readkey-perl.

Ngoài ra, để lưu một vài ký tự, chương trình này không khôi phục chế độ nhập thành bình thường khi thoát, vì vậy bạn có thể thấy mình không thể thấy những gì bạn đang gõ sau đó. Thực hiện lệnh shell stty sanehoặc resetnên sửa nó. Vấn đề này có thể được khắc phục, với chi phí thêm 10 byte, với:

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

Phần thưởng: quine thuần túy, 81 byte

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

Một lần nữa, dòng mới sau dấu phẩy chỉ cần thiết để đáp ứng tối thiểu năm khoảng trắng.

Không giống như chương trình 56 byte ở trên, phiên bản này thực sự không cần phải đọc mã nguồn của chính nó, vì nó dựa trên một câu hỏi - cụ thể, trên câu hỏi này:

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

Điều hay ho của quine này là nó có thể dễ dàng mang một "trọng tải" tùy ý trong q{ }khối, mà không phải lặp lại. Mặc dù nó không thể đánh bại <0>trong thời gian ngắn, nhưng nó đã trở nên khá gần.

Lưu ý: Chương trình này sử dụng saytính năng Perl 5.10+ và do đó cần phải được gọi bằng công tắc dòng lệnh -M5.010(hoặc -E). Theo sự đồng thuận đã thiết lập về meta, các công tắc như vậy được sử dụng để kích hoạt các tính năng ngôn ngữ hiện đại không được tính là ký tự phụ . Giải pháp ngắn nhất tôi có thể tìm thấy mà không saycó 83 byte:

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

Cả hai cũng có thể được làm cho thân thiện hơn với thiết bị đầu cuối bằng cách (nối hai dòng cuối cùng và) chèn:

;ReadMode
0

trước khi người cuối cùng }.


Ồ Chỉ là wow. Rất tuyệt.
ThisSuitIsBlackNot

+1, nhưng tôi khuyên bạn nên có thói quen gõ stty sanethay vì reset(có thể, trên một số os, đôi khi đang làm gì đó hơn là chỉ đặt lại một số tham số đầu cuối ^^)
Olivier Dulac

Giải pháp rất hay. FWIW, open F,$0<F>có thể được thay thế bằng open 0<0>. Ngoài ra, tôi sẽ lập luận rằng một bài đăng trong meta không thực sự tạo thành sự đồng thuận. Tùy chọn -M5.01không "đưa ngôn ngữ đến một điểm cụ thể" , như tác giả gợi ý, nó cho phép các tính năng. Không có phiên bản perl mà các tính năng này được bật theo mặc định.
primo

3
@primo: Vui lòng gửi câu trả lời của riêng bạn cho chuỗi meta, nếu bạn không đồng ý với câu hỏi hiện có. Thực tế là không ai làm như vậy trong ba năm rưỡi, cho đến nay, cho thấy mức độ đồng thuận hợp lý, ít nhất là trong số các nhà quản lý ở đây, những người tích cực truy cập meta, nhưng sự đồng thuận luôn có thể thay đổi. (Dù sao, theo cách tôi thấy, nếu ruby golfscript.rb foo.gsđược tính là một lệnh hợp lệ để chạy một chương trình được viết bằng GolfScript, thì perl -M5.010 foo.plnên tính là một lệnh hợp lệ để chạy một chương trình được viết trong "Perl 5.10". Nhưng các đối số như vậy thực sự thuộc về meta, chứ không phải đây.)
Ilmari Karonen

5

Python 3 - 124 byte - 7 khoảng trắng


Mã số:

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

Ung dung:

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()

Phiên bản theo kiểu:

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

Hồng ngọc, 85 , 71

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

Quá tệ đó IO#rawkhông phải là một phần của thư viện tiêu chuẩn.

Cải thiện

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

Điều này giúp loại bỏ lệnh gọi Kernel # exit và sử dụng các biến toàn cục để rút ngắn mã.


4

Befunge - 21

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

Tôi khá hài lòng với điều này, vì tôi vừa tìm hiểu về Befunge. Nếu bạn không ngại "gõ" vào cửa sổ bật lên, bạn có thể chạy nó ở đây hoặc ở đây cho đến khi tôi tìm thấy một trình thông dịch trực tuyến tốt hơn.


2

Powershell, 89

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

2

Trăn 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)

Đó là một câu đố. Rút ngắn từ 507 bằng cách sử dụng execvà di chuyển một số báo cáo xung quanh.


2

C, 211 186 byte

Giải pháp của tôi trong C sử dụng thư viện nguyền rủa. Nó có thể dài hơn các giải pháp C khác, nhưng nó là một quine. Mặc dù câu hỏi không bắt buộc, nó vẫn khá đẹp. Nó cũng hoạt động khá độc đáo:

#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)))

Một phiên bản dễ đọc hơn với một số ý kiến ​​và nội dung:

#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)))

biên dịch với:

gcc -o h h.c -lncurses

2

C - 136 135 132 byte (chỉ dành cho 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();} 

Lưu ý: có một khoảng trống ở cuối chương trình, có lẽ sẽ không hiển thị.

Tôi không thể đảm bảo chương trình này sẽ hoạt động trên một máy tính khác ngoài máy tính của tôi vì nó rất khủng khiếp. Mọi thứ sẽ trở nên đơn giản hơn rất nhiều khi mọi người chỉ có máy 32 bit. Sau đó, tôi sẽ không cần phải lo lắng về sizeof(int*)việc 8 (chắc chắn là vậy; tôi đã in nó ra để đảm bảo) trong khi sizeof(int)là 4.

Hạnh phúc, tên của tệp thực thi được lưu trữ trong chuỗi đầu tiên trong argv. Tuy nhiên, đặt một con trỏ làm đối số cho hàm có nghĩa là tôi phải chỉ định rõ ràng loại TẤT CẢ các đối số cho hàm - nghĩa là tôi sẽ phải gõ inthai lần - một sự lãng phí rất lớn các ký tự. May mắn thay tôi tìm thấy một cách giải quyết. Tôi đã có đối số thứ hai là chính, qchỉ là một int khác. Sau đó gán qcho một biến loại int**bằng cách nào đó được quản lý để lấy tất cả các byte cần thiết từ ngăn xếp.

Tôi đã không thành công trong việc tìm kiếm bất kỳ thủ thuật nào như vậy để diễn giải kiểu trả về fopennhư một con trỏ mà không khai báo hàm.

Chỉnh sửa: Thông báo Tôi nên sử dụng ~fscanf(*v,"%s",b)thay vì vì fscanf(*v,"%s",b)>0lợi nhuận là -1 khi đạt EOF.


Phân biệt này cho tôi để tôi không thể kiểm tra nó, nhưng bạn sẽ có thể khai báo một con trỏ void ( void **v;) thay vì tạo mẫu fopen().
Comitern

@Comi INTERN thay đổi này không giúp tôi lưu trữ kết quả chính xác fopen. Tôi không thấy lý do tại sao thay thế void cho int sẽ tạo ra sự khác biệt, vì tất cả các con trỏ đều có cùng kích thước.
frageum

Điểm tốt. Vẫn ngắn hơn và ổn định hơn để chỉ cần khai báo một con trỏ mặc dù - đây thực sự chạy cho tôi: 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();}(Tôi đã phải thay thế getchar()cho getch()dù).
Comitern

@Comi INTERN mã của bạn vẫn gặp sự cố trên hệ thống của tôi, nhưng công việc tốt đẹp khiến nó hoạt động. Tôi đoán nó giống như tôi đã nói - mỗi phiên bản của chương trình sẽ chạy trên 1 máy tính.
frageum

Tại sao bạn không sử dụng nguyên mẫu K & R? Vd *fopen()thay vì *fopen(a,b)?
FUZxxl 17/2/2015

1

Perl - 87 byte

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

Tôi đã không thấy bất cứ điều gì trong các quy tắc về những việc cần làm sau khi tệp đã được đọc đến cuối, vì vậy nó chỉ đơn giản là chờ đợi đầu vào sau khi in đoạn cuối cùng.


1

node.js với LiveScript:

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

phiên bản không đồng bộ:

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

1

Rắn hổ mang - 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 rất hữu ích


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}}})()

Cả 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 (chrome):

( 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
        }
    }
})()

Có hai phiên bản, vì Chrome không xử lý chức năng mũi tên và bảng điều khiển không bị xóa theo cùng một phương thức

Firefox one hoạt động với fireorms, dường như bảng điều khiển dành cho nhà phát triển mặc định không thể bị xóa khỏi tập lệnh.


Bạn có bỏ lỡ yêu cầu người dùng phải nhấn các phím ngẫu nhiên để in đầu ra không?
Tối ưu hóa

chắc chắn rồi!, sẽ viết lại cái này
Hqueto

0

Groovy - 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)
}   

Vì không có getch()hoặc tương đương trong các ngôn ngữ Java và Java-esque như Groovy ... về cơ bản, mã của tôi không xử lý các phím nhấn. Đó là tất cả: D


0

C, 248 ký tự

Quine đúng

Chỉ hoạt động trong unix, trong các cửa sổ, nó sẽ được thực hiện bằng cách sử dụng _getch.

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 và Javascript, 232 byte

<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>

Các quine Javascript truyền thống, nhưng sửa đổi.

JSFiddle ở đây .


0

SmileBASIC, 79 75 byte

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

Rất dễ dàng để có được một LINE cụ thể của một chương trình trong SmileBASIC, vì vậy tôi chỉ cần đặt khoảng trắng trước mỗi lần ngắt dòng. Tôi nghĩ rằng tôi rất thông minh, đặt các khoảng trắng trước mỗi lần ngắt dòng, nhưng rõ ràng chúng ta được phép sử dụng ngắt dòng thay vì khoảng trắng ...

Giải trình:

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 

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.