การเขียนโปรแกรมด้วย Bits และ Bytes


40

ในการท้าทายนี้คุณจะต้องเขียนล่ามเป็นภาษาง่ายๆที่ฉันได้ทำขึ้น ภาษานี้ใช้ตัวสะสม A ตัวเดียวซึ่งมีความยาวหนึ่งไบต์ ที่จุดเริ่มต้นของโปรแกรม A = 0 นี่คือคำแนะนำภาษา:

!: ผกผัน

คำสั่งนี้จะแปลงค่าตัวสะสมเล็กน้อย ทุกศูนย์กลายเป็นหนึ่งและทุก ๆ กลายเป็นศูนย์ ! ง่าย

>: เลื่อนไปทางขวา

คำสั่งนี้เลื่อนทุกบิตในที่เดียวไปทางขวา บิตซ้ายสุดจะกลายเป็นศูนย์และบิตขวาสุดจะถูกทิ้ง

<: เลื่อนไปทางซ้าย

คำสั่งนี้เลื่อนทุกบิตในที่เดียวทางซ้าย บิตขวาสุดจะกลายเป็นศูนย์และบิตซ้ายสุดจะถูกทิ้ง

@: สลับ Nybbles

คำสั่งนี้ทำการแลกเปลี่ยนสี่บิตบนสุดของ A ด้วยสี่บิตด้านล่าง ตัวอย่างเช่นถ้า A 01101010และคุณดำเนินการ@A จะเป็น10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

นั่นคือคำแนะนำทั้งหมด! ง่ายใช่มั้ย

กฎระเบียบ

  • โปรแกรมของคุณต้องยอมรับอินพุตหนึ่งครั้งในตอนเริ่มต้น นี่จะเป็นบรรทัดของรหัส นี่ไม่ใช่ล่ามแบบโต้ตอบ! คุณสามารถยอมรับอินพุตได้เพียงครั้งเดียวและไม่ต้องวนกลับไปที่จุดเริ่มต้นอีกครั้งเมื่อบรรทัดนั้นถูกดำเนินการ
  • โปรแกรมของคุณต้องประเมินอินพุตดังกล่าว อักขระทุกตัวที่ไม่ได้กล่าวถึงข้างต้นจะถูกละเว้น
  • โปรแกรมของคุณควรพิมพ์ค่าสุดท้ายของแอคคูมูเลเตอร์เป็นทศนิยม
  • ใช้กฎมาตรฐานสำหรับภาษาการเขียนโปรแกรมที่ถูกต้อง
  • ช่องโหว่มาตรฐานไม่ได้รับอนุญาต
  • นี่คือนับจำนวนไบต์ที่เล็กที่สุดชนะ

ต่อไปนี้เป็นโปรแกรมขนาดเล็กเพื่อทดสอบการส่งของคุณ ก่อนที่ลูกศรจะเป็นรหัสหลังจากได้ผลลัพธ์ที่ต้องการ:

  • ! -> 255
  • !>> -> 63
  • !<@ -> 239
  • !nop!&6*! -> 255

สนุก!


ฉันคิดว่าจาก! -> 255ที่เราจะใช้ 8 บิตต่อไบต์ที่นี่ คำถามไม่ชัดเจน
Toby Speight

3
@TobySpeight ไบต์โดยนิยามคือ 8 บิต
HyperNeutrino

คำตอบ:


15

Pyth, 36 35 ไบต์

u%@[t_G/G2yGi_jGJ16JG)x"!><@"H256z0

สายรัดทดสอบ

การเป็นตัวแทนภายในของตัวสะสมเป็นจำนวนเต็ม จำนวนเต็มนี้ถูกดัดแปลงโดย 256 ในแต่ละการวนซ้ำตามที่ต้องการ การดำเนินงานที่ดำเนินการอยู่-G-1, G/2, G*2และGแปลงเป็นฐาน 16 กลับและแปลงกลับไปที่ฐาน 10 ซึ่งGเป็นสะสม

ฉันพลาดเรื่องการเพิกเฉยทุกอย่าง สิ่งนี้ได้รับการแก้ไขแล้ว ขอบคุณ @Dennis


ดังนั้น-G-1จะสั้นกว่า~Gใน Pyth? ฉันค่อนข้างสงสัยว่า
เครื่องคิดเลข

รหัสในคำถามที่เป็นจริงt_Gที่_เป็นผลทางลบและเป็นt -1ใน Pyth ~หมายถึงบางสิ่งที่แตกต่างอย่างสิ้นเชิง
isaacg

ฉันหมายถึง Python ~(ไม่ใช่ระดับบิต)
CalculatorFeline

@CalculatorFeline จุดของฉันคือไม่มีฟังก์ชั่น 1 ตัวอักษรที่มีผลใน Pyth ดังนั้นรหัสข้างต้น (อย่างน้อยสำหรับการดำเนินการนั้น) จะดีเท่าที่จะได้รับ
isaacg

13

C, 96

สมมติว่าอินพุต ASCII (หรือเทียบเท่า):

a;main(c){while(c=getchar()+1)a=(c^34?c^61?c^63?c^65?a:a*257/16:a/2:a*2:~a)&255;printf("%u",a);}

tidier:

a;
main(c){
  while(c=getchar()+1)
    a=(c^34?
      c^61?
        c^63?
          c^65?
            a
          :
            a*257/16
        :
          a/2
      :a*2:~a
    )&255;
  printf("%u",a);
}

โดยพื้นฐานแล้วมันเป็นเพียงชุดของนิพจน์ประกอบไปด้วยหลายระดับ ฉันกำลังเพิ่มค่าที่ได้รับจากการgetchar()ที่ EOF (-1) ส่งผลให้มีค่าเป็นศูนย์และออกจากโปรแกรม

(ลิงค์ ideone)


1
ฉันลองตัวเองและฉันก็เขียนรหัสเดียวกันเกือบทั้งหมด Btw โปรแกรมของคุณจะไม่ลดลงเล็กน้อยเมื่อเลื่อนขึ้นไปข้างบน (อินพุต: !<>ควรส่งผล127และไม่ได้255) กำหนดaว่าเป็นของคุณcharหรือใช้บรรทัดa&=255(และใช้%u) เพื่อให้ได้ผลที่ถูกต้อง นอกจากนี้คุณสามารถลดการปฏิเสธของคุณจะa^255 นอกจากนี้ยังสั้นกว่าของคุณ ~aa>>4&15(a&240)/16
MarcDefiant

อ่าจุดดี ปรากฎว่ามันมีประสิทธิภาพมากกว่าในการซ่อนส่วนล่าง 8 บิตในแต่ละการวนซ้ำ
ossifrage คลื่นไส้

1
ในกรณีนี้คุณสามารถใช้สตริงรูปแบบ%uแทน%hhu
MarcDefiant

1
ฉันเพิ่งเห็นมันในตอนนี้ แต่คุณสามารถใช้a/16|a*16แทนa/16|(a&15)*16ได้ &255บิตไม่กี่ด้านบนจะถูกนำออกโดย
MarcDefiant

1
การปรับปรุงเล็ก ๆ : เป็นหนึ่งไบต์สั้นกว่าa*257/16 a/16|a*16
Toby Speight

11

Python 3, 133 ไบต์

ใช้พจนานุกรมเพื่อชดเชยการขาดไวยากรณ์ตัวพิมพ์ใน Python ดูเพิ่มเติมได้ที่นี่

a="0"*8
for i in input():a={"!":''.join(str(1-int(b))for b in a),"<":a[1:]+"0",">":"0"+a[:-1],"@":a[4:]+a[:4]}.get(i,a)
print(int(a,2))

แอคคูมูเลเตอร์คือสตริงซึ่งถูกแปลงเป็นเลขฐาน 10 ตอนท้าย

ตัวอย่าง I / O:

$ python3 bitsnbytes.py
!
255
$ python3 bitsnbytes.py
!>>
63
$ python3 bitsnbytes.py
!<@
239
$ python3 bitsnbytes.py
!nop!&6*!
255

ถ้ามันเป็นล่ามที่ใช้งานได้จริงมันน่าจะเป็นfor i in sys.stdin::)
Zizouz212

4
@ Zizouz212 ฉันเชื่อว่าคุณหมายถึงว่ามันเป็นแบบโต้ตอบ; มันดูเหมือนล่ามตัวจริงสำหรับฉัน ;)
Alex A.

9

Javascript (ES6), 80 91 90 ไบต์

a=>[...a].reduce((p,c)=>c=='!'?p^255:c=='<'?p*2%256:c=='>'?p>>1:c=='@'?p/16|0+p%16*16:p,0)

สั้นมากเท่าที่จะทำได้ กำหนดฟังก์ชั่นที่ไม่ระบุชื่อซึ่งใช้โปรแกรมเป็นอินพุต

  • สำหรับ!ใช้เวลาx XOR 255เป็นของ JS ~จะพิจารณาจำนวนx32 บิต
  • สำหรับ<คูณxด้วย 2 และรับผลลัพธ์ mod 256
  • สำหรับ>ให้เลื่อนบิตx1 บิตไปทางขวาอย่างแท้จริง
  • สำหรับ@พื้นและเพิ่มความมันx/16x%16*16

ขอบคุณ @vihan ที่แนะนำให้ใช้reduceเพื่อบันทึกไบต์


คุณสามารถใช้<เพื่อบันทึกประมาณ 4 ไบต์ การใช้การลดอาจช่วยประหยัดไบต์ได้ด้วย
Downgoat

1
@vihan คุณหมายถึง<สถานที่==หรือไม่ ถ้าเป็นเช่นนั้นนั่นจะไม่ทำงานเนื่องจากอักขระที่ไม่มี op-op จะทำงานไม่ถูกต้อง ฉันใช้วิธีนี้ในโซลูชัน 80- ไบต์ก่อนหน้าของฉัน
ETHproductions

ไม่ใช่ ES6 fat arrow ที่เป็นมาตรฐานบน PPCG ที่คุณต้องกำหนดใช่มั้ย
MayorMonty

@SpeedyNinja ฉันไม่รู้จักมาตรฐานดังกล่าว แต่ถ้าคุณสามารถชี้ให้ฉันโพสต์เกี่ยวกับหนึ่งฉันจะแก้ไขคำตอบของฉัน
ETHproductions

8

CJam, 37 ไบต์

0q{"!><@"#"~ 2/ 2* GmdG*+ "S/=~255&}/

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

0                   e# Push 0 (accumulator).
q                   e# Read from STDIN.
{                   e# For each character in the input:
  "!><@"#           e#   Find its index in "!><@" (-1 if not found).
  "~ 2/ 2* GmdG*+ " e#   Push that string.
  S/                e#   Split at spaces to push ["~" "2/" "2*" "GmdG*+" ""].
                    e#     "~"      : signed 64-bit bitwise NOT
                    e#     "2/"     : divide by 2
                    e#     "2*"     : multiply by 2
                    e#     "GmdG*+" : (x) -> (x/16) (x%16) -> (16(x%16) + (x/16))
                    e#     ""       : NOOP
  =~                e#  Select the corresponding string and evaluate it.
  255&              e#  Zero all but the 8 least significant bits.
}/                  e#

8

Java (8), 514 483 411 366 359 239 224 229 198 194 187 186 184 182 181 180 177 ตัวอักษร

ว้าวนี่มันมีจำนวนมากลงมาแล้ว! ขอบคุณทุกคนที่ให้คำแนะนำกับฉัน! ฉันซาบซึ้งมาก!

interface T{static void main(String[]g)throws Exception{int i,a=0;while((i=System.in.read())!=10)a=(i==33?255-a:i==62?a/2:i==60?a*2:i==64?a>>4|a<<4:a)%256;System.out.print(a);}}

ไบต์ Golfed 31 (!) โดยการปรับการสลับแทปด้วยการดำเนินการระดับบิตเมื่อเทียบกับInteger.???วิธีที่มีความยาว

Golfed 72 (!!!!) ตัวอักษรโดยการลบสตริงที่ไม่จำเป็นที่สร้างขึ้นเพื่อแลกเปลี่ยน nibbles ดีขึ้นกว่าก่อน!

ตัวอักษร Golfed 45 (!!) โดยการลบการใช้งานjava.util.Scannerและการอ่านSystem.inโดยตรง โปรดทราบว่าตอนนี้นิพจน์แลมบ์ดาหายไปแล้ว Java 8 ไม่ต้องการอีกต่อไป! เพียงแค่ Java 1 จะทำ!

Golfed 7 ตัวอักษรโดยสร้างคลาส(default)(ลบpublicคำค้นหา) ด้วย @bmarks

แข็งแรงเล่นกอล์ฟ 120 (!!!!!!!) ตัวอักษรด้วยการเปลี่ยนทุกคนที่มีความยาวการดำเนินงานในระดับพลิกบิตไปInteger 255 - aตอนนี้มันสั้นกว่ามาก!

Golfed 15 (!) ตัวอักษรโดยการแปลงกะเป็นการคูณและการหารลบวงเล็บปีกกาออกจากคำสั่ง while และทำให้aท้องถิ่นในmainวิธีการ

Ungolfed 9 = (ตัวอักษรเนื่องจากปัญหากับกะซ้ายไม่ทิ้งไบต์ซ้ายสุดดังนั้นตอนนี้ฉันทำmod (256)กะขวาจะทำให้หมายเลขผลลัพธ์สั้นลงกว่าเดิมหนึ่งบิตดังนั้นจึงไม่จำเป็นต้องใช้modกะขวา สิ่งที่ฉันสับจะสลับ 4 บิตสุดท้ายและบิตสุดท้ายที่สองและand (&)ตัดบิตอื่น ๆ ทั้งหมดโปรแกรม Inversion ของฉันไม่ได้ทำให้เกิดปัญหาใด ๆ หากหมายเลขเดิมน้อยกว่า 256

Golfed 31 35 chars ขอบคุณ @Geobits โดยการแปลงswitchข้อความให้เป็นประโยคไตรภาคจำนวนมากและยังแปลง chars ให้เป็น ints ทำให้ตัวอักษรสั้นลง

แข็งแรงเล่นกอล์ฟ 7 ตัวอักษรโดยการลบที่ไม่จำเป็น&240ในการแลกเปลี่ยนตอด ( (a&240)>>4การa>>4และการแปลง(a&15)<<4ไปa<<4&240. การเปลี่ยนแปลงสุดท้ายเท่านั้นแข็งแรงเล่นกอล์ฟ แต่ตัวละครตัวหนึ่ง

แข็งแรงเล่นกอล์ฟ 1 ถ่านโดยการลบที่ไม่จำเป็น=ในa /= 2เพราะจะเทียบเท่ากับa = a /= 2a = a / 2

แข็งแรงเล่นกอล์ฟ 2 ตัวอักษรด้วยการเปลี่ยนไปprintlnprint

แข็งแรงเล่นกอล์ฟ 2 ตัวอักษรโดยการลบโดยไม่ตั้งใจa=ในa=255-a( a=a=255-aเทียบเท่ากับa=255-a)

แข็งแรงเล่นกอล์ฟ 1 ถ่านด้วยการเปลี่ยนเข้าสู่a<<4&240a%16<<4

แข็งแรงเล่นกอล์ฟ 1 ถ่านโดยการเพิ่มวงเล็บที่ด้านนอกของงบ ternary %256และทำ วิธี%16นี้ไม่จำเป็นในส่วนการเลื่อนซ้ายของการสลับแทะ วงเล็บเพิ่ม 2 ตัวอักษรและ%16บันทึก 3 ตัว

แข็งแรงเล่นกอล์ฟ 3 ตัวอักษรโดยการเปลี่ยนclassไปinterfaceและลบpublicโดยใช้วิธีการแบบคงคุณลักษณะอินเตอร์เฟซ Java 8 ขอบคุณ @TheNumberOne (ไม่มีความคิดเห็น แต่หาคำตอบของเขาใน "เคล็ดลับสำหรับการเล่นกอล์ฟใน Java"


ฉันไม่คิดว่าชั้นจะต้องเปิดเผยต่อสาธารณะ นอกจากนี้ฉันคิดว่าถ้าคุณสร้าง Integer แทนที่จะเป็น int คุณสามารถทำ a.parseInt, a.toString ฯลฯ แทน Integer.parseInt, Integer.toString ฯลฯ
คั่นหน้า

ขอบคุณสำหรับคำแนะนำแรก; ฉันจะลบIntegerวิธีการเรียนทั้งหมด
HyperNeutrino

บางทีคุณสามารถทำได้ในขณะที่ ((i = System.in.read ())> 10) แทนที่จะเป็น! = 10 เพื่อบันทึกไบต์?
bmarks

ความคิดที่ดี แต่ถ้ามีอะไรต่ำกว่า 10 จะทำให้โปรแกรมยุติและฉันควรจะละเว้นตัวละครอื่น ๆ ไม่ทำตอนท้ายของโลก (หรืออย่างน้อยโปรแกรมของฉัน :)) ฉันจะพิจารณามัน; อาจไม่มีอักขระ ASCII ที่ถูกต้องต่ำกว่า 10
HyperNeutrino

4
มันแทบจะไม่คุ้มค่าที่จะใช้switchในขณะที่เล่นกอล์ฟ case/ breakเป็นเพียงยาวเกินไป คุณน่าจะประหยัดได้โดยการทำให้ทุกอย่างเป็นไตรภาค สิ่งที่ต้องการa=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a;
Geobits

7

สนิม121 121ไบต์

fn r(s:&str)->u8{let mut n=0u8;for t in s.chars(){match t{'!'=>n=!n,'>'=>n/=2,'<'=>n<<=1,'@'=>n=n>>4|n<<4,_=>()}}n}

วิ่งตัวอย่าง:

fn main() {
    println!("{}", r("!"));    //=> 255
    println!("{}", r("!>>"));  //=> 63
    println!("{}", r("!<@"));  //=> 239
}

Ungolfed:

fn run_ungolfed(s: &str) -> u8 {
    let mut n = 0u8;
    for t in s.chars() {
        match t {
            '!' => n = !n,
            '>' => n >>= 1,
            '<' => n <<= 1,
            '@' => n = (n >> 4) | (n & 15) << 4,
            _ => ()
        }
    }
    n
}

น่าแปลกที่สั้นสำหรับสนิม ไม่มีอะไรน่าสนใจนอกจากความจริงที่ว่าฉันได้เรียนรู้กฎมาก่อนมากขึ้นในวันนี้ - ใคร(a>>b)|cจะรู้เหมือนกันa>>b|c?

โกนไบต์ออกโดยเปลี่ยนn>>=1เป็นn/=2; แม้กระนั้นเดียวกันก็ไม่สามารถทำได้ด้วยการคูณเพราะล้นเลขคณิตเป็นความหวาดกลัว (เช่นความผิดพลาด) ใน Rust


2
สิ่งที่มีความสำคัญทำให้รู้สึกเมื่อคุณมั่นใจตัวเองว่า>>คือการจัดเรียงเช่นการแบ่งและ|เป็นการจัดเรียงเช่นนอกจากนี้
ลินน์

6

HP 41C / CV / CX (? bytes, 42 ขั้นตอน)

เพียงเพื่อหัวเราะคิกคักนี่คือสำหรับเครื่องคิดเลข HP 41C / CV / CX (ต้องใช้โมดูล Extended Function หรือ 41CX สำหรับฟังก์ชั่น ATOX) เครื่องคิดเลขไม่ได้รายงานขนาดโปรแกรมเป็นไบต์โชคไม่ดี

ใส่โปรแกรมของคุณลงในการลงทะเบียนอัลฟ่าซึ่งค่อนข้างยุ่งยากเนื่องจากไม่มีทางเข้า! หรือ @ โดยตรงจากแป้นพิมพ์ (ใช้ XTOA ด้วยรหัส ASCII 33 และ 64 ตามลำดับเพื่อต่อท้าย)

ขั้นตอนที่ 08 และ 10 อนุญาตให้ละเว้น opcodes ที่ไม่ถูกต้อง ลบพวกเขาเพื่อบันทึก 2 ขั้นตอน แต่โปรแกรมจะผิดพลาดในการป้อนข้อมูลที่ไม่ถูกต้อง

01 LBL"BB
02 0
03 LBL A
04 ATOX
05 X=0?
06 GTO E
07 X<>Y
08 SF 25
09 XEQ IND Y
10 CF 25
11 GTO A
12 LBL 33
13 255
14 X<>Y
15 -
16 RTN
17 LBL 60
18 2
19 *
20 256
21 MOD
22 RTN
23 LBL 62
24 2
25 /
26 INT
27 RTN
28 LBL 64
29 RCL X
30 16
31 /
32 INT
33 X<>Y
34 16
35 *
36 256
37 MOD
38 +
39 RTN
40 LBL E
41 RDN
42 RTN

6

Python 2, 79 ไบต์

ฉันรู้ว่าฉันได้ทำอะไรบางอย่างที่คล้ายกับใน Python ก่อนหน้านี้ นี่เป็นเพียงพอร์ตของคำตอบ Ruby ของฉันแต่มันก็เป็นคำตอบที่สั้นที่สุดของ Python ในตอนนี้: D

a=0
for i in raw_input():a=[~a,a/2,a*2,a*16+a/16,a]["!><@".find(i)]&255
print a

ข้อแตกต่างจากรุ่น Ruby คือว่าอันนี้จะไม่เพิกเฉยต่อคำสั่งที่ไม่ถูกต้องในขณะที่วนซ้ำอินพุต แต่ฉันใช้ประโยชน์จากข้อเท็จจริงที่ว่า Python มีแนวโน้มที่จะกลับมา-1แทนที่nilเมื่อไม่มีการจับคู่ - มูลค่าปัจจุบันของaถูกผนวกเข้ากับด้านหลังของอาร์เรย์ผลลัพธ์ดังนั้นคำสั่งที่ไม่ถูกต้องทั้งหมดจะจับคู่กับค่าเดิมที่ไม่เปลี่ยนแปลง


4

Python 3, 124 94 93 ไบต์

a=0
for i in input():
 if i in"!><@":a=(i=='!')*(255-a)+(i==">")*a//2+(i=="<")*(a+a)%256+(i=="@")*(16*(a%16)+a//16)
print(a)

"!" เหมือนกับการลบจาก 255
"<" เหมือนกับการคูณด้วย 2 แต่การลงทะเบียน 8 บิตหมายถึง mod 256
">" เหมือนกับการหารจำนวนเต็ม 2
"@" หมายถึงการเลื่อน 4 บิตสุดท้าย ( a%16) โดย 4 บิต ( *16) และเพิ่มสี่บิตแรก ( a/16)

แก้ไข (อ่านการคัดลอกไร้ยางอาย)
เห็นคำตอบอื่น ๆ ในหลาม (จากการสลายตัวของเบต้า) มันใช้วิธีที่มีประสิทธิภาพจริงๆในการจำลองกรณีสวิตช์โดยใช้พจนานุกรม ใช้ว่าเราสามารถเขียน

a=0
for i in input():a={"!":255-a,"<":a<<1&255,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)
print(a)

ขอขอบคุณ Beta Decay


ไม่ว่าคุณจะทำอะไรคุณต้องลด mod ลง256ใช่มั้ย a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256ดังนั้นทำไมไม่ทำอย่างนั้นที่สิ้นสุด: สิ่งนี้จะช่วยให้คุณประหยัดไบต์ทันที (เพราะคุณจะทำa*2แทนa<<1) ... แต่คำตอบของ @daniero ยังแสดงให้เห็นว่าถ้าคุณทำแบบนี้ก็(a%16)<<4จะถูกตัดให้สั้นลงa<<4เพราะบิต 16 หรือใหญ่กว่านั้นจะถูกกำจัดเมื่อคุณคูณ ได้ 16 และลดมัน mod 256 ดี! นอกจากนี้คุณยังสามารถแทนที่255-aโดย-1-a... ~aหรือดีกว่าโดยเพียงแค่ โดยรวมแล้วคำแนะนำเหล่านี้ควรช่วยให้คุณประหยัด 9 ไบต์
mathmandan

3

Haskell, 89 ไบต์

a#'!'=255-a
a#'>'=div a 2
a#'<'=mod(a*2)256
a#'@'=mod(a*16)256+div a 16
a#_=a
f=foldl(#)0

ตัวอย่างการใช้: f "!>>"->63


3

สนิม 111 ไบต์

มีความคิดเห็นเพิ่มเติมเกี่ยวกับคำตอบของ @ Doorknob แต่ฉันไม่มีความคิดเห็นใด ๆ เมื่อฉันเพิ่งสร้างบัญชี

หนึ่งสามารถโกน 10 ไบต์จากโซลูชัน Rust ของเขาด้วยสิ่งต่อไปนี้:

fn r(s:&str)->u8{let mut n=0u8;for t in s.chars(){n=match t{'!'=>!n,'>'=>n>>1,'<'=>n<<1,'@'=>n>>4|n<<4,_=>n}}n}

ฉันคิดว่าเราสามารถทำให้ใช้งาน fold ได้สั้นลง ( doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold ) แต่น่าแปลกใจที่ทำให้มันยาวขึ้น
user4867444

3

Python 3, 127 ไบต์

แก้ไข: shorting ขอบคุณ @Jakube

แก้ไข 2: แก้ไขขอบคุณ @Anachor

a=0
for i in input():a=(a^255if i=="!"else a>>1if i==">"else a<<1if i=="<"else(a&15)<<4|(a&240)>>4if i=="@"else a)&255
print(a)

อาจเป็นเพราะบรรทัดใหม่ของ windows นั่นคือบวกสองไบต์ ฉันจะใช้ตัวนับไบต์นั้นในครั้งต่อไป :-) ขอบคุณ
uno20001

โปรดทราบว่านี่ไม่ได้ทิ้งบิตซ้ายสุดเมื่อซ้ายขยับดังนั้น!<ให้510ในขณะที่มันควรจะเป็น254
Rohcana

ฉันหวังว่าตอนนี้มันจะ ขออภัยสำหรับความผิดพลาดของฉันนี่เป็นความท้าทายครั้งแรกของฉัน "กอล์ฟ"
uno20001

3

Ceylon, 297 290

shared void y(){value t=process.readLine()else"";variable Byte a=0.byte;for(c in t){switch(c)case('!'){a=a.not;}case('>'){a=a.rightLogicalShift(1);}case('<'){a=a.leftLogicalShift(1);}case('@'){a=a.and(#f0.byte).rightLogicalShift(4).xor(a.and(#f.byte).leftLogicalShift(4));}else{}}print(a);}

จัดรูปแบบ:

shared void y() {
    value t = process.readLine() else "";
    variable Byte a = 0.byte;
    for (c in t) { switch (c)
        case ('!') { a = a.not; }
        case ('>') { a = a.rightLogicalShift(1); }
        case ('<') { a = a.leftLogicalShift(1); }
        case ('@') { a = a.and(#f0.byte).rightLogicalShift(4).xor(a.and(#f.byte).leftLogicalShift(4)); }
        else {} }
    print(a);
}

#fและ#f0เป็นตัวเลขฐานสิบหกสำหรับ nibbles .byteแปลงจำนวนเต็มเป็นไบต์ ฉันโชคดีที่.stringแอตทริบิวต์ของ Byte ใช้การแทนแบบไม่ได้ลงนามของ byte Ceylon ยังมีคุณสมบัติคำสั่ง switch โดยไม่ล้มลงและสตริงเป็นรายการของตัวละครซึ่งสามารถทำซ้ำได้

ฉันยังพยายามตัดชื่อวิธีการเลื่อนแบบยาวเหล่านั้นด้วยการใช้การนำเข้า aliasing แต่จริง ๆ แล้วจะกลายเป็น 7 ไบต์อีกต่อไป:

import ceylon.language{Byte{r=rightLogicalShift,l=leftLogicalShift}}shared void x(){value t=process.readLine()else"";variable Byte a=0.byte;for(c in t){switch(c)case('!'){a=a.not;}case('>'){a=a.r(1);}case('<'){a=a.l(1);}case('@'){a=a.and(#f0.byte).r(4).xor(a.and(#f.byte).l(4));}else{}}print(a);}

จัดรูปแบบ:

import ceylon.language {
    Byte {
        r=rightLogicalShift,
        l=leftLogicalShift
    }
}
shared void x() {
    value t = process.readLine() else "";
    variable Byte a = 0.byte;
    for (c in t) {
        switch (c)
        case ('!') { a = a.not; }
        case ('>') { a = a.r(1); }
        case ('<') { a = a.l(1); }
        case ('@') { a = a.and(#f0.byte).r(4).xor(a.and(#f.byte).l(4)); }
        else {}
    }
    print(a);
}

สิ่งนี้อาจมีประโยชน์หากเราต้องการวิธีการเหล่านั้นบ่อยขึ้น


3

ทับทิม, 81 73 ไบต์

ง่ายกว่านี้มาก - ไม่มีเลย! สำหรับอักขระที่ใช้ได้แต่ละตัวในอินพุตนั้นจะประเมินแต่ละคำสั่งและค้นหาคำสั่งที่เหมาะสมผ่านดัชนีของ$&(อักขระปัจจุบันในอินพุต)

a=0
gets.scan(/[!><@]/){a=[~a,a/2,a*2,a*16+a/16]["!><@".index$&]&255}
p a

1
นั่นเป็นอัจฉริยะ สั้นกว่าที่อื่นมาก 2 upvotes โดยฉัน!
edc65

คุณจะเพิ่มคะแนนโหวตเป็นสองเท่าได้อย่างไร ...
HyperNeutrino

@JamesSmith เขาอาจจะหมายถึงนี้และฉันคำตอบหลาม :)
daniero

@danerio ฉันเห็น
HyperNeutrino

2

STATA, 197 ไบต์

di _r(a)
gl b=0
forv x=1/`=length("$a")'{
gl c=substr("$a",`x',1)
if"$c"=="!" gl b=255-$b
if"$c"==">" gl b=int($b/2)
if"$c"=="<" gl b=mod($b*2,256)
if"$c"=="@" gl b=mod($b,16)*16+int($b/16)
}
di $b

Ungolfed

display _request(a) //get the input via prompt and put in var a
global b=0 //initialise A to be 0
forv x=1/`=length("$a")'{ //for loop from 1 to last char in a
global c=substr("$a",`x',1) //get the char at index x in a
if "$c"=="!" global b=255-$b //invert is the same as 255-A
if "$c"==">" global b=int($b/2) //right shift is the same as A/2 (with integer division)
if "$c"=="<" global b=mod($b*2,256) //left shift is the same as A*2%256
if "$c"=="@" global b=mod($b,16)*16+int($b/16) //nibble swap is the same as A%16*16+A/16
}
display $b //display the result of A

ไม่ทำงานกับล่ามออนไลน์และต้องการล่ามเริ่มต้นที่ไม่ต้องเสียค่าใช้จ่าย นี่จะค่อนข้างง่ายขึ้นกับการทำงานระดับบิตที่แท้จริง แต่ฉันไม่คิดว่ามันจะมีประโยชน์สำหรับการใช้งานทั่วไปของ STATA


ทำไมล่ามออนไลน์ไม่ทำงาน
CalculatorFeline

2

JavaScript, 104

[].reduce.call(prompt(),function(a,i){return(i=='!'?~a:i=='>'?a/2:i=='<'?a*2:i=='@'?a>>4|a<<4:a)&255},0)

ผู้ประกอบการประกอบไปด้วยแผนที่ที่ให้คำแนะนำ

BITWISE AND ถูกใช้เพื่อ จำกัด ประเภท Number ของเราเป็นไบต์เดียว


2

Julia, 117 94 86 73 ไบต์

p->(a=0x0;[a=c==33?~a:c==60?a<<1:c==62?a>>1:c!=64?a:a<<4|a>>4for c=p];1a)

นี่คือฟังก์ชันที่ไม่ระบุชื่อที่ยอมรับสตริงและส่งคืนจำนวนเต็ม หากต้องการเรียกใช้กำหนดค่าให้กับตัวแปร

Ungolfed:

function f(p)
    # Initialize the accumulator to 0 as an 8-bit unsigned integer
    a = 0x0

    # Loop over the characters in the input
    for c in p
        a = c == 33 ? ~ a :        # '!'
            c == 60 ? a << 1 :     # '<'
            c == 62 ? a >> 1 :     # '>'
            c != 64 ? a :          # no-op
            a << 4 | a >> 4        # '@'
    end

    # Convert the accumulator to a regular integer and return
    return Int(a)
end

บันทึก 8 ไบต์ด้วย Sp3000 และ 13 ขอบคุณ Dennis!


2

JavaScript (ES6), 76 81

เป็นฟังก์ชันที่ไม่มีชื่อส่งคืนค่าตัวสะสม

นี่คือการย้ายคำตอบที่ชาญฉลาดโดย @daniero (ที่มี upvotes น้อยเกินไป)

โบนัส: คุณสามารถส่งผ่านค่าเริ่มต้นของแอคคูมูเลเตอร์ได้ หากไม่ผ่านค่าเริ่มต้นคือ 0 ตามที่ระบุ

(p,a)=>(p.replace(/[!<>@]/g,i=>a=(i<'<'?~a:i<'>'?a*2:i<'@'?a/2:a*257/16)&255),a)

ทดสอบการเรียกใช้ตัวอย่างข้อมูลด้านล่างในเบราว์เซอร์ EcmaScript 6 (ฉันทดสอบใน Firefox)

f=(p,a)=>[...p].map(c=>a=255&[a,~a,a*2,a/2,a*257/16][1+'!<>@'.indexOf(c)])|a

// TEST
out=x=>O.innerHTML+=x+'\n'

function go(x) { out(x+' -> '+f(x)) }

go('!'),go('!>>'),go('!<@'),go('!nop!&6*!')

// LESS GOLFED
F=(p,a)=>// a as a parameter, if not passed its value starts as undefined, then becomes NaN, but the operators '&' and '~' treat it as 0
  [...p].map(c => // execute following function for each character p
    a = 255 & // any intermediate result is converted to numeric and truncate to a byte          
   // evaluate all possible results (then choose one bases on the current character)
   [a,   // NOP, if unexpected char 'a' remains the same
    ~a,  // tilde == binary not (will give a result wider than a byte)
    a*2, // < shift left is *2 (can give a result wider than a byte) 
    a/2, // > shift right is /2 (can give a non integer result)
    a *257 / 16  // move nibbles around (will give a result wider than a byte)
   ] // array of all results
   [1+'!<>@'.indexOf(c)] // find index to get the correct result
  ) // end map, returns an array in any case
    // eventually a single element array containg a
  | a // return accumulator
Test program:<input id=I><button onclick='go(I.value)'>go</button>
<pre id=O></pre>



1

C # 193

void Main(){byte a=0;foreach(var c in Console.ReadLine()){if(c=='!')a=(byte)~a;if(c=='>')a=(byte)(a>>1);if(c=='<')a=(byte)(a<<1);if(c=='@')a=(byte)(((a&240)>>4)|((a&15)<<4));}Console.Write(a);}

2
คุณไม่ต้องการusing System;หรืออะไรทำนองนั้นในการเข้าถึงConsole.ReadLineและConsole.Writeไม่มีส่วนSystem.นำหน้าใช่ไหม
Alex A.

นอกจากนี้ยังดูเหมือนว่าคุณไม่ควรที่จะโยนbyteสำหรับการดำเนินการแต่ละครั้ง แต่ฉันอาจจะผิด
Alex A.

1

ลัวะ 344 ถ่าน

a=string.rep("0",8)
t=io.read()
f={["!"]=function()local s="";for j=1,8 do s=s..(a:sub(j,j)=="0"and"1"or"0") end;return s end,[">"]=function() return "0"..a:sub(1,7) end,["<"]=function()return a:sub(2,8).."0"end,["@"]=function()return a:sub(5,8)..a:sub(1,4)end}
for i=1,#t do a=(f[t:sub(i,i)]or function()return a end)()end
print(tonumber(a,2))

แรงบันดาลใจจากการใช้ @Beta Decay ของการสะสมสตริงเห็นว่า lua ไม่มีประเภทไบต์ อาจจะตีกอล์ฟมากขึ้นโดยใช้ฟังก์ชั่นน้อยลง


1

R, 194 ไบต์

b<-readline();A<-rep(0,8);s<-strsplit(b,"")[[1]];for(r in s){if(r=="!")A<-(A+1)%%2;if(r==">")A<-c(0,A)[1:length(A)];if(r=="<")A<-c(A,0)[-1];if(r=="@")A<-c(A[5:8],A[1:4])};print(sum(A*(2^(7:0))))

ungolfed

b <- readline()
A <- rep(0, 8) 
s <- strsplit(b, "")[[1]]
for (r in s) {
    if (r == "!")
        A <- (A + 1) %% 2
    if (r == ">")
        A <- c(0, A)[1:length(A)]
    if (r == "<")
        A <- c(A, 0)[-1]
    if (r == "@")
        A <- c(A[5:8], A[1:4])
}
print(sum(A*(2^(7:0))))

ทั้งหมด<-สามารถถูกแทนที่ด้วย=ที่นี่ซึ่งช่วยลดรหัสโดย 7 ไบต์ นอกจากนี้คุณอาจสามารถแทนที่ชุดของifข้อความสั่งด้วยการโทรเพียงครั้งเดียวไปยังswitch(ดังในA=switch(r,"!"=(A+1)%%2, ...))
plannapus

ผลลัพธ์b=readline();A=rep(0,8);s=strsplit(b,"")[[1]];for(r in s)A=switch(r,"!"=(A+1)%%2,">"=c(0,A)[1:length(A)],"<"=c(A,0)[-1],"@"=c(A[5:8],A[1:4]),A);print(sum(A*(2^(7:0))))คือ 167 ไบต์
plannapus

1

RPL, 170.5 ไบต์

อินพุตควรถูกป้อนเป็นสตริงในระดับ 1

\<< DEC 8 STWS \-> S 
    \<< #0d 1 S SIZE 
        FOR I "!><@" S I DUP SUB POS 1 + { \<< \>> NOT SR SL \<< DUP #16d / SWAP #16d * + \>> } SWAP GET EVAL NEXT \>> 
\>>

1

K, 57 ไบต์

มันเป็นการเริ่มต้น:

0{y+2*x}/(8#0){((~:;{-1_0,x};{1_ x,0};4!;{x})"!><@"?y)x}/

ทดสอบโดยใช้ Kona:

  f:0{y+2*x}/(8#0){((~:;{-1_0,x};{1_ x,0};4!;{x})"!><@"?y)x}/
...
  f'("!";"!>>";"!<@";"!nop!&6*!")
255 63 239 255

ฉันอาจจะทำได้ดีกว่าใน k5 แต่มันเป็นชุดที่ซับซ้อนของการแลกเปลี่ยน - ตัวอย่างเช่นการแปลงเลขฐานสองเป็นทศนิยมนั้นง่ายเหมือน2/แต่พฤติกรรมของการ?ทำให้เป็นเรื่องยากที่จะจัดการกรณีเริ่มต้นสำหรับการค้นหาคำสั่ง


1

PHP, 189 ไบต์

<? $c='00000000';foreach(str_split($argv[1])as$a){$a=='!'&&$c=strtr($c,'01','10');$a=='<'&&$c=substr($c.'0',1);$a=='>'&&$c=substr('0'.$c,0,8);$a=='@'&&$c=substr($c.$c,4,8);}echo bindec($c);

ไม่ใช่ว่ามันจะเอาชนะคำตอบมากมายมันเป็นเพียงเพื่อการฝึกฝน


1

HPPPL , 302 294 ไบต์

#pragma mode(separator(.,;)integer(d8))EXPORT b()BEGIN print();local p,j,a;a:=#0d;INPUT({{p,[2]}});for j from 1 to dim(p)do c:=p(j);case if c==33 then a:=BITNOT(a)end if c==62 then a:=BITSR(a,1)end if c==60 then a:=BITSL(a,1)end if c==64 then a:=BITSL(a,4)+BITSR(a,4)end end;end;print(a*1);END;

Ungolfed:

// make sure integers are unsigned 8 bit decimal numbers
#pragma mode( separator(.,;) integer(d8) ) 
EXPORT b()
BEGIN
  print();
  local p,j,a;
  a:=#0d;                         // set a to integer value 0
  INPUT({{p,[2]}});               // open input dialog treating input as string ( type [2])
  for j from 1 to dim(p) do
    c:=p(j);
    case
      if c==33 then a:=BITNOT(a) end             // !
      if c==62 then a:=BITSR(a,1) end            // >
      if c==60 then a:=BITSL(a,1) end            // <
      if c==64 then a:=BITSL(a,4)+BITSR(a,4) end // @
    end;
  end;
  print(a*1); // converts to proper output by promoting to non integer format
              // print(a) would result in
              // #239:8d for 239 if the default bit size is not set to 8 bits decimal
              // indicating an 8 bit unsigned decimal integer, or
              // #239d if the default bit size is already set to 8 bits decimal

END;

คำสั่งอินพุต HPPPL

HPPPL เอาต์พุตไปยังเทอร์มินัล

คำตอบนี้ทำให้มั่นใจได้ว่า HP Prime ใช้จำนวนเต็ม 8 บิตที่ไม่ได้ลงชื่อแม้ว่าโหมดจะถูกตั้งค่าเป็น 64 บิตโดยผู้ใช้ หากเครื่องคิดเลขถูกตั้งค่าด้วยตนเองให้ใช้เลขจำนวนเต็มฐานสิบ 8 บิตแบบไม่ได้ลงนามpragmaคุณสามารถละเว้นคำสั่งได้ หากการส่งออกไม่จำเป็นต้องทำตามรูปแบบอย่างเคร่งครัดแล้วในตอนท้ายก็สามารถa*1 aการคูณผลลัพธ์ด้วย 1 เพียงแค่ทำให้แน่ใจว่าผลลัพธ์ไม่เป็นไปตามเอาต์พุตภายในสำหรับค่าจำนวนเต็ม printคำสั่งในบรรทัดที่ 4 ยังสามารถละเว้นถ้าขั้วไม่ต้องล้างก่อนที่จะพิมพ์ออกผล หากอนุญาตให้ส่งผ่านโปรแกรมเป็นอาร์กิวเมนต์สตริงจะINPUTสามารถละเว้นคำสั่งได้เช่นกัน

นี่เป็นเวอร์ชั่นที่สั้นที่สุดที่มีอินพุตและเอาต์พุตที่เหมาะสมโดยไม่มีอาร์กิวเมนต์ pragma (หากเครื่องคิดเลขถูกตั้งค่าเป็น Uint8 โดยค่าเริ่มต้น:

243 ไบต์:

EXPORT b()BEGIN local p,j,a;a:=#0d;INPUT({{p,[2]}});for j from 1 to dim(p)do c:=p(j);case if c=33 then a:=BITNOT(a)end if c=62 then a:=BITSR(a,1)end if c=60 then a:=BITSL(a,1)end if c=64 then a:=BITSL(a,4)+BITSR(a,4)end end;end;print(a*1);END;

1

Perl 6, 96 89 ไบต์

{my $a=0;$a=(+^*,*+<1,*+>1,{$_+<4+$_+>4},{$_})["!<>@".index($_)//4]($a)%256 for .comb;$a}

โซลูชันเก่า:

{my $a=0;$a=(255-*,*+<1+&255,*+>1,{$_+&15+<4+$_+>4},{$_})["!<>@".index($_)//4]($a)for .comb;$a}

1

C #, 119 ไบต์

i=>{var a=0;foreach(var c in i){if(c=='!')a=~a;if(c=='>')a>>=1;if(c=='<')a<<=1;if(c=='@')a=a<<4|a>>4;a&=255;}return a;}

รุ่นอื่นที่ฉันพยายาม แต่ต้องการไบต์มากกว่านี้:

Func<string,int>C=i=>{var a=0;foreach(var c in i){switch(c){case'!':a=~a;break;case'<':a<<=1;break;case'>':a>>=1;break;case'@':a=a<<4|a>>4;break;}a&=255;}return a;};

// This is, despite having the worst score, my personal favourite :D
Func<string,int>D=i=>{var f=new Dictionary<char,Func<int,int>>{{'!',q=>~q},{'<',q=>q<<1},{'>',q=>q>>1},{'@',q=>q<<4|q>>4}};var a=0;foreach(var c in i)if(f.ContainsKey(c))a=f[c](a)&255;return a;};

1

Python 2.7.3, 104 ไบต์

การมีโค้ดในสตริงที่จะถูกประเมินจะดูค่อนข้างสกปรก แต่ใช้งานได้: D

a=0
for c in raw_input():a=eval({'!':'~a','<':'a<<1','>':'a>>1','@':'a<<4|a>>4'}.get(c,'a'))&255
print a

นี่คือผลลัพธ์ (และการป้อนข้อมูลจริง .. )

และใช่มันทำงานบน RaspberryPi :)

ตัวอย่างผลลัพธ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.