การเข้ารหัสแบบไบนารี


11

นี้อยู่บนพื้นฐานxkcd #

สร้างโปรแกรมหรือฟังก์ชั่นที่ตั้งชื่อซึ่งใช้พารามิเตอร์ 2 ตัวซึ่งแต่ละตัวเป็นสตริงหรือรายการหรืออาร์เรย์ของไบต์หรือตัวอักษร พารามิเตอร์ที่สองจะมีเฉพาะอักขระที่ดึงมาจากlrfu(หรือ ASCII ที่เทียบเท่าไบต์) ควรตีความเป็นชุดคำสั่งที่จะดำเนินการในลำดับบิตที่แสดงโดยพารามิเตอร์แรก

การประมวลผลที่ดำเนินการจะต้องเทียบเท่ากับสิ่งต่อไปนี้:

  1. แปลงพารามิเตอร์แรกเป็นบิตสตริงเดียวที่เกิดขึ้นจากการเชื่อมบิตของอักขระแต่ละตัว (ตีความว่าเป็นหนึ่งใน 7 บิต ASCII, ASCII ที่ขยายเพิ่ม 8 บิตหรือการเข้ารหัส Unicode มาตรฐาน) เช่นถ้าพารามิเตอร์แรกเป็น"AB"เช่นนี้จะเป็นหนึ่งใน10000011000010(7-bit), 0100000101000010(8-bit หรือ UTF-8) 00000000010000010000000001000010, หรือ01000001000000000100001000000000(UTF-16 ในสอง endiannesses) เป็นต้น
  2. สำหรับอักขระแต่ละตัวในพารามิเตอร์ที่สองตามลำดับให้ดำเนินการคำสั่งที่สอดคล้องกัน:
    • lหมุน bitstring ที่เหลือหนึ่งอัน เช่นจะกลายเป็น1000001100001000000110000101
    • rหมุนบิตสตริงขวาหนึ่ง เช่นจะกลายเป็น1000001100001001000001100001
    • fพลิก (หรือสลับกลับ) แต่ละบิตใน bitstring เช่นจะกลายเป็น1000001100001001111100111101
    • uฝืน bitstring เช่นจะกลายเป็น1000001100001001000011000001
  3. แปลง bitstring เป็นสตริง ASCII ซึ่งใช้หนึ่งอักขระต่อบิต เช่นจะกลายเป็น10000011000010 "10000011000010"นี่เป็นเพราะไม่ใช่ทุกชุด 7/8 บิตมีอักขระที่กำหนดให้

ตัวอย่าง (ใน Python):

>>> f("b", "rfu")
01110011

มันจะเปลี่ยน"b"เป็นตัวแทนไบนารี ASCII 8 บิตของ01100010มันหมุนไปทางขวา ( 00110001) พลิกแต่ละบิต ( 11001110) และกลับด้าน ( 01110011)

มีความยืดหยุ่น

ตัวละครอื่น ๆ อาจจะนำมาใช้แทนของตัวละครl, r, fและuแต่พวกเขาต้องได้รับการบันทึกไว้อย่างชัดเจน

ป้ายบอกคะแนน

ขอบคุณ@Optimizerสำหรับการสร้างข้อมูลโค้ดต่อไปนี้ วิธีใช้คลิก "แสดงตัวอย่างข้อมูล" เลื่อนไปที่ด้านล่างและคลิก "►เรียกใช้ข้อมูลโค้ด"


3
พารามิเตอร์ที่สองสามารถเป็นอะไร เป็นไปได้"rrfrburb"ไหม นอกจากนี้เมื่อหนึ่งกะหรือกลับบิตหนึ่งจะทำมันสำหรับตัวอักษรแต่ละตัวหรือสตริงโดยรวมหรือไม่ กรณีทดสอบเพิ่มเติมจะทำให้ชัดเจนยิ่งขึ้น
xnor

1
คุณหมายถึงกะหรือหมุน? leftshift ใน C จะส่งผลให้บิตซ้ายสุดหายไปและบิตขวาสุดกลายเป็นศูนย์ สำหรับการเลื่อนเวลาไปยังหมายเลขที่ไม่ได้ลงชื่อจะมีการสลับเกิดขึ้น สำหรับหมายเลขที่เซ็นชื่อฉันไม่แน่ใจว่ามีพฤติกรรมที่กำหนดในระดับสากลสำหรับสิ่งที่ได้รับการเลื่อนสำหรับตัวเลขลบ (คือ 0 หรือ 1 หรือไม่) ทั้งสองทางข้อมูลจะหายไปเสมอเมื่อมีการเลื่อนซึ่งไม่ได้เป็นเช่นนั้น สำหรับการหมุน
เลเวลริเวอร์เซนต์

2
FWIW มีหนึ่งคำถามตาม XKCDนั้นแล้ว
Peter Taylor

2
@flawr ฉันไม่คิดว่ามันจะมีข้อได้เปรียบกว่าความสามารถที่มีอยู่ในการค้นหา 'xkcd'
Peter Taylor

1
@KSFT ฉันคิดว่าฉันจะต้องปฏิเสธไม่ได้ ทำให้เป็นสตริงด้วยการเข้าร่วม

คำตอบ:


1

CJam, 34 32 ไบต์

1l+256b2b1>l{~"11W:mm%!<>">4%~}/

มันใช้ตัวอักษรต่อไปนี้สำหรับคำแนะนำ:

0: left rotation
1: right rotation
2: reverse
3: flip

อินพุตกำลังรับจาก STDIN โดยใช้คำบนบรรทัดแรกและสตริงคำสั่งบนบรรทัดที่สอง

ทดสอบที่นี่

คำอธิบาย

การรับบิตสตริงเป็นเพียงเรื่องของการตีความรหัสอักขระเป็นตัวเลขของตัวเลขฐาน -256 (และรับการเป็นตัวแทนฐาน 2) สิ่งที่ยุ่งยากคือการแปลงฐานหลังจะไม่ปัดผลลัพธ์ด้วย 0s ทางซ้าย ดังนั้นฉันเพิ่ม 1 นำไปสู่การป้อนข้อมูลเริ่มต้นแล้วแยก 1 นั้นอีกครั้งในการเป็นตัวแทนไบนารี ตัวอย่างเช่นถ้าใส่เป็นabผมเปิดที่เป็นอาร์เรย์[1 'a 'b]ตีความว่าเป็นฐาน-256 (ตัวละครจะถูกแปลงโดยอัตโนมัติไปยังรหัสอักขระ) ซึ่งเป็น90466และไปยังฐาน-2 [1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0]ซึ่งเป็น ตอนนี้ถ้าฉันเพิ่งลบผู้นำที่1ฉันมีบิตสตรีมที่ฉันกำลังมองหา

นั่นคือสิ่งที่ส่วนนี้ของรหัสทำ:

1l+256b2b1>

ตอนนี้ฉันอ่านรายการคำสั่งและดำเนินการบล็อกสำหรับแต่ละอักขระในสตริงคำสั่ง:

l{...}/

สิ่งแรกที่ต้องทำคือการประเมินผลที่เกิดขึ้นจริงตัวอักษรและเลข0, 1, หรือ2 3ตอนนี้เวทย์มนตร์กอล์ฟที่แท้จริง ... ขึ้นอยู่กับคำสั่งฉันต้องการเรียกใช้โค้ดสั้น ๆ ที่ใช้งาน:

Integer:  Code  Operation
0         1m<   "Left rotation";
1         1m>   "Right rotation";
2         W%    "Reverse";
3         :!    "Flip each bit";

ฉันสามารถเก็บสิ่งเหล่านี้ไว้ในอาร์เรย์ของบล็อกและเลือกบล็อกที่ถูกต้องเพื่อให้ทำงานได้ แต่การเข้ารหัสในสตริงนั้นสั้นกว่าจริง:

"11W:mm%!<>">4%~

ก่อนอื่นฉันใช้การเชื่อมโยงจำนวนเต็มกับคำสั่งเพื่อตัดการเริ่มต้นของสตริง ดังนั้นสำหรับการหมุนซ้ายสตริงจะไม่เปลี่ยนแปลงสำหรับการหมุนขวาตัวอักษรแรกจะถูกยกเลิกและอื่น ๆ 4%จากนั้นผมเลือกตัวละครทุกตัวที่สี่จากสตริงที่เริ่มต้นจากครั้งแรกด้วย สังเกตเห็นว่ามีการแจกจ่ายข้อมูลโค้ดสี่ชุดทั่วทั้งสตริงอย่างไร ~ในที่สุดผมก็เพียงแค่ประเมินสตริงเป็นรหัสที่มี

สตริงบิตจะถูกพิมพ์โดยอัตโนมัติเมื่อสิ้นสุดโปรแกรม


ทำไม1m<มากกว่า(+? คุณกำลังทำงานกับอาเรย์มากกว่าตัวเลขใช่ไหม?
ปีเตอร์เทย์เลอร์

@ ปีเตอร์โอ้ถูกต้องขอบคุณ ฉันจะแก้ไขในภายหลัง
Martin Ender

2

CJam, 34 ไบต์

อีกวิธีใน CJam

1l+256b2b1>l_S/,1&@f=_,,@f{W%~}\f=

ข้อความอินพุตอยู่บนบรรทัดแรกและคำแนะนำอยู่บนบรรทัดที่สอง

คำแนะนำ:

)        Rotate left.
(        Rotate right.
 (space) Flip.
~        Reverse.

1
มันค่อนข้างฉลาด ความอับอายที่f~ไม่ได้นำมาใช้จริงใช่ไหม ;)
Martin Ender

2

Pyth 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

การใช้งาน:

0    : rotate right
1    : rotate left
2    : reverse order
3    : flip values

Github Pyth

ลองออนไลน์ได้ที่นี่

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

AbC
0321

คำอธิบาย:

                                    : z=input() (implicit)
jk                                  : join("", ...)
  u@[                 )sHw          : reduce(select from [...] the value at int(H), input(), ...)
     +eGPG                          : [ G[-1] + G[:1],
          +tGhG                     : G[1:] + G[1],
               _G                   : G[::-1],
                 ms!dG              : map(lambda d: int(not(d)), G) ]
                          smjCk2z   : first arg = sum(map(lambda k:convert_to_base(ord(k),2),z)

บางสิ่งที่ฉันไม่สามารถบีบได้: Pyth reduceใช้Gสำหรับค่าก่อนหน้าโดยอัตโนมัติและHสำหรับค่าถัดไป


การสูญเสียการสัมผัสของคุณ? สั้นกว่า CJam เพียง 1 ไบต์?
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer จริงๆแล้วฉันสามารถเอาชนะมันได้โดยใช้คำแนะนำเดียวกัน แต่ฉันไม่คิดว่าสิ่งนี้จะใช้ได้เพราะความท้าทายบอกว่า " อาจใช้ตัวอักษรอื่นแทนlrfuแต่จะต้องมีเอกสารชัดเจน" (เน้นที่เหมือง)
Martin Ender

1

สกาลา - 192

def f(i:String,l:String)=(i.flatMap(_.toBinaryString).map(_.toInt-48)/:l){
case(b,'l')⇒b.tail:+b.head
case(b,'r')⇒b.last+:b.init
case(b,'f')⇒b.map(1-_)
case(b,'u')⇒b.reverse}.mkString

1

Matlab (166 ไบต์)

ใช้ตัวอักษรabcdแทนlrfuตามลำดับ

function D=f(B,C)
D=dec2bin(B,8)';
D=D(:);
g=@circshift;
for c=C
switch c-97
case 0
D=g(D,-1);
case 1
D=g(D,1);
case 2
D=char(97-D);
case 3
D=flipud(D);
end
end
D=D';

เทคนิคบางอย่างใช้ที่นี่เพื่อประหยัดพื้นที่:

  • การใช้abcdตัวอักษรช่วยให้ฉันลบ97ครั้งเดียวแล้วตัวอักษรกลายเป็น0, 1, ,2 3สิ่งนี้ช่วยประหยัดพื้นที่ในswitch-caseอนุประโยค
  • การกำหนดcircshiftเป็นฟังก์ชั่นนิรนามหนึ่งตัวอักษรยังช่วยประหยัดพื้นที่เนื่องจากมันถูกใช้สองครั้ง
  • เนื่องจากDประกอบด้วย'0'และ'1'ตัวอักษร (รหัส ASCII 48และ49) คำสั่งที่D=char(97-D)สอดคล้องกับการผกผันระหว่าง'0'และ'1'ค่า โปรดทราบว่าสิ่งนี้97ไม่เกี่ยวข้องกับสิ่งที่อ้างถึงข้างต้น
  • คอมเพล็กซ์ผัน transpose 'ใช้แทน .'transpose

0

Python 2 - 179

b="".join([bin(ord(i))[2:]for i in input()])
for i in input():b=b[-1]+b[:-1]if i=="r"else b[1:]+b[0]if i=="l"else[str("10".find(j))for j in b]if i=="f"else b[::-1]
print"".join(b)

0

C #, 418 ไบต์

using System;using System.Collections.Generic;using System.Linq;class P{string F(string a,string o){var f=new Dictionary<char,Func<string,IEnumerable<char>>>{{'l',s=>s.Substring(1)+s[0]},{'r',s=>s[s.Length-1]+s.Substring(0,s.Length-1)},{'u',s=>s.Reverse()},{'f',s=>s.Select(c=>(char)(97-c))}};return o.Aggregate(string.Join("",a.Select(c=>Convert.ToString(c,2).PadLeft(8,'0'))),(r,c)=>new string(f[c](r).ToArray()));}}

จัดรูปแบบ:

using System;
using System.Collections.Generic;
using System.Linq;

class P
{
    string F(string a, string o)
    {
        // define string operations
        var f = new Dictionary<char, Func<string, IEnumerable<char>>>
        {
            {'l', s => s.Substring(1) + s[0]},
            {'r', s => s[s.Length - 1] + s.Substring(0, s.Length - 1)},
            {'u', s => s.Reverse()},
            {'f', s => s.Select(c => (char) (97 - c))}
        };
        // for each operation invoke f[?]; start from converted a
        return o.Aggregate(
            // convert each char to binary string, pad left to 8 bytes and join them
            string.Join("", a.Select(c => Convert.ToString(c, 2).PadLeft(8, '0'))),
            // invoke f[c] on result of prev operation
            (r, c) => new string(f[c](r).ToArray())
        );
    }
}

0

J, 164

([: >@:}. (([: }. >&{.) ; >@:{.@:>@:{. 128!:2 >@:}.)^:({.@:$@:>@:{.))@:(>@:((<;._1 ' 1&|."1 _1&|."1 -. |."1') {~ 'lrfu' i. 0&({::)@:]) ; ;@:([: (8$2)&#: a. i. 1&({::)))

จัดรูปแบบ:

nextop=:([: }. >&{.)
exec=: (>@:{.@:>@:{.) apply"1 >@:}.
times=: ({.@:$@:>@:{.)
gapply=: [: >@:}. (nextop ; exec)^:(times) f.

tobin=: ;@:([: (8#2)&#:(a.i.1&{::))
g=:'1&|.';'_1&|.';'-.';'|.'
tog =:  g {~ ('lrfu' i. 0&{::@:])
golf=: gapply @: (>@:tog;tobin)  f.

ตัวอย่าง

golf ('rfu';'b')
0 1 1 1 0 0 1 1


golf ('lruuff';'b')
0 1 1 0 0 0 1 0

(8#2)#: 98
0 1 1 0 0 0 1 0

golf ('lruuff';'AB')
0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0

tobin '';'AB'
0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0

0

JavaScript (E6), 163 167

ใช้ฟังก์ชั่นที่มีชื่อพร้อมพารามิเตอร์อาร์เรย์ 2 ตัว

  • พารามิเตอร์ตัวแรกอาร์เรย์ของไบต์ที่สอดคล้องกับรหัสอักขระ 7 บิต
  • พารามิเตอร์ที่สอง, อาร์เรย์ของไบต์ที่สอดคล้องกับอักขระ ASCII 'F', 'L', 'R', 'U' -> 70, 76, 82, 85

ฟังก์ชันส่งคืนสตริงอักขระที่ประกอบด้วย '1' และ '0'

F=(a,s,r='')=>
  a.map(c=>r+=(128|c).toString(2).slice(-7))-
  s.map(c=>a=c<71?a.map(c=>1-c):c<77?a.concat(a.shift):c<83?[a.pop(),...a]:a.reverse(),a=[...r])
  ||a.join('')

ตัวอย่างการ f("b", "rfu")แปลF([98],[82,70,85])ผลลัพธ์คือ0111001

หมายเหตุการใช้สตริงอักขระมีความยาวมากใน javascript! จำนวนไบต์186

F=(a,s,r='')=>
  [for(c of a)r+=(128|c.charCodeAt()).toString(2).slice(-7)]-
  [for(c of(a=[...r],s))a=c<'G'?a.map(c=>1-c):c<'M'?a.concat(a.shift):c<'S'?[a.pop(),...a]:a.reverse()]
  ||a.join('')

ตัวอย่าง F("b", "RFU")ผลลัพธ์เป็น0111001อีกครั้ง


0

ทับทิม, 151

f=->i,s{s.chars.inject(i.unpack("B*")[0]){|a,c|
a.reverse! if c==?u
a.tr!"01","10" if c==?f
a<<a.slice!(1..-1) if c==?l
a<<a.slice!(0..-2) if c==?r
a}}

ค่อนข้างตรงไปตรงมา วนซ้ำอักขระในsและดำเนินการกับตัวละครใด ๆ


0

Python 2, 142

j="".join
f=lambda S,I:reduce(lambda s,i:[s[1:]+s[0],s[-1]+s[:-1],s[::-1],j([`1^int(c)`for c in s])][int(i)],I,j([bin(ord(c))[2:]for c in S]))

คล้ายกับคำตอบของ pyth ในวิธีการ: ฉันสร้างรายการของสตริงและดัชนีทั้งหมดขึ้นอยู่กับค่าของสตริงคำสั่งที่ฉันทำซ้ำโดยใช้การลด

การใช้งาน:

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