İkili şifreleme


11

Bu, xkcd # 153'e dayanmaktadır .

Her biri bir dize veya bir bayt veya karakter listesi veya dizisi olan 2 parametre alan bir program veya adlandırılmış işlev yapın. İkinci parametre yalnızca lrfu(veya eşdeğer ASCII baytlarından) çizilen karakterleri içerir . İlk parametre ile temsil edilen bir bit dizisi üzerinde gerçekleştirilecek bir dizi talimat olarak yorumlanmalıdır.

Gerçekleştirilen işlem aşağıdakilere eşit olmalıdır:

  1. İlk parametreyi, her karakterin bitlerini birleştirerek oluşturulan tek bir bit dizisine dönüştürün (7 bit ASCII, 8 bit genişletilmiş ASCII veya standart Unicode kodlaması olarak yorumlanır). Örneğin, ilk parametre "AB"bu ise bu 10000011000010(7 bit), 0100000101000010(8 bit veya UTF-8) 00000000010000010000000001000010veya 01000001000000000100001000000000(iki endianitede UTF-16), vb.
  2. İkinci parametredeki her karakter için sırasıyla ilgili komutu yürütün:
    • lbit dizesini sola döndürür. Örneğin 10000011000010olur 00000110000101.
    • rbit dizesini sağa döndürür. Örneğin 10000011000010olur 01000001100001.
    • fbit dizesindeki her biti çevirir (veya tersine çevirir). Örneğin 10000011000010olur 01111100111101.
    • ubit dizisini tersine çevirir. Örneğin 10000011000010olur 01000011000001.
  3. Bit dizisini, bit başına bir karakter kullanan bir ASCII dizesine dönüştürün. Örneğin 10000011000010olur "10000011000010". Bunun nedeni, 7/8 bitlik tüm kümelerin kendilerine atanmış bir karakteri olmamasıdır.

Örnek (Python'da):

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

Bu döner "b", 8-bitlik ASCII ikili gösterimi içine 01100010doğru döndüğü o (, 00110001), her bit (çevirir 11001110) ve tersine çevirir onu ( 01110011).

Esneklik

Diğer karakterler Karakterler yerine kullanılabilir l, r, f, ve u, ancak açıkça belgelenmiş olmalıdır.

sayı tahtası

Aşağıdaki kod snippet'ini oluşturduğu için @Optimizer'a teşekkürler . Kullanmak için, "Kod snippet'ini göster" i tıklayın, en alta kaydırın ve "► Kod snippet'ini çalıştır" ı tıklayın.


3
İkinci parametre ne olabilir? Olabilir mi "rrfrburb"? Ayrıca, bir kişi bitleri değiştirdiğinde veya ters çevirdiğinde, her harf veya bir bütün olarak dize için mi yapılır? Daha fazla test örneği daha net hale getirecektir.
xnor

1
Şunu mu demek istediniz? C'deki bir sol kaydırma, en soldaki bitin kaybolmasına ve en sağdaki bitin sıfırlanmasına neden olur. İmzasız bir numarada bir hak kayması için bunun tersi olur. İşaretli bir sayı için, negatif sayılar için kaydırılan şeyin evrensel olarak tanımlanmış bir davranışı olup olmadığından emin değilim (0 veya 1 mi?) Her iki durumda da, bir vardiya gerçekleştirildiğinde bilgi her zaman kaybolur; döndürmek için.
Level River St


2
@flawr, mevcut 'xkcd' arama
Peter Taylor

1
@KSFT Sanırım buna hayır demem gerekecek. Birleştirerek bir dize yapın.

Yanıtlar:


1

CJam, 34 32 bayt

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

Talimatlar için aşağıdaki karakterleri kullanır:

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

Giriş, STDIN'den ilk satırdaki kelime ve ikinci satırdaki komut dizesi ile alınır.

Burada test edin.

açıklama

Bit dizesini elde etmek gerçekten de karakter kodlarını bir taban-256 sayısının rakamları olarak yorumlamakla ilgilidir (ve taban-2 temsilini almak). Zor olan şey, ikinci taban dönüşümünün sonucu solda 0'lar ile doldurmayacağıdır. Bu nedenle, ilk girdiye önde gelen 1 ekledim ve sonra ikili gösterimde bu 1'i yeniden ayırdım. Örnek olarak, eğer giriş ise ab, bunu bir diziye çeviririm [1 'a 'b], taban-256 (karakterler otomatik olarak karakter kodlarına dönüştürülür), 90466ve taban-2'ye yorumlanır [1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0]. Şimdi o lideri 1kaldırsam aradığım bit akışını elde ederim.

Kodun bu kısmı bunu yapar:

1l+256b2b1>

Şimdi talimat listesini okudum ve talimat dizesindeki her karakter için bir blok yürütüyorum:

l{...}/

Yapılacak ilk şey karakterini ve gerçek tamsayılar değerlendirmektir 0, 1, 2veya 3. Şimdi gerçek golf büyüsü ... talimatlara bağlı olarak operasyonu uygulayan kısa bir kod parçası çalıştırmak istiyorum:

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

Bu bloklar bir dizi saklamak ve çalıştırmak için doğru bloğu seçin, ancak bunları bir dizede kodlamak aslında daha kısa:

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

İlk olarak, dizenin başlangıcını dilimlemek için talimatla ilişkilendirilmiş tamsayı kullanın. Sola dönüş için dize değişmez, sağa dönüş için ilk karakter atılır ve bu şekilde devam eder. Sonra dizeden her dördüncü karakteri, ilkinden başlayarak seçiyorum 4%. Dört kod parçacığının dize boyunca nasıl dağıtıldığına dikkat edin. Sonunda sadece dize ile kod olarak değerlendirmek ~.

Bit dizesi, programın sonunda otomatik olarak yazdırılır.


Neden 1m<daha çok (+? Sayı yerine bir dizi üzerinde çalışıyorsun, değil mi?
Peter Taylor

@Peter oh doğru, teşekkürler. Bunu daha sonra çözeceğim.
Martin Ender

2

CJam, 34 bayt

CJam'de bir başka yaklaşım.

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

Giriş metni ilk satırda ve talimatlar ikinci satırdadır.

Talimatlar:

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

1
Bu oldukça zekice. f~Gerçi uygulanmayan bir utanç , değil mi? ;)
Martin Ender

2

Pyth 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

Kullanım Alanları:

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

Pyth github

Burada çevrimiçi deneyin.

Bu, dizeyi ilk argüman olarak ve komut dizesini ikinci argüman olarak alan bir programdır. Çevrimiçi sürümde, dizeleri yeni bir satırla ayrılmış şekilde vermelisiniz, şöyle:

AbC
0321

Açıklama:

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

Oldukça sıkamadığım bir şey: Pyth'ler reduceotomatik olarak Gönceki değer ve Hsonraki değer için kullanır .


Dokunuşunu mu kaybediyorsun? CJam'den sadece 1 bayt daha mı kısa?
Doktor

@Optimizer Aslında, aynı talimatları kullanarak bunu yenebilirim. Ancak bunun geçerli olacağını düşünmedim çünkü meydan okuma "Bunun yerine başka harfler de kullanılabilir lrfu, ancak açık bir şekilde belgelenmeleri gerekir." (Vurgu madeni)
Martin Ender

1

Scala - 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 bayt)

Bu abcd, lrfusırasıyla yerine harfler kullanır .

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

Yer kazanmak için burada kullanılan bazı püf noktaları:

  • Kullanımı abcdharfleri beni çıkarma sağlayan 97bir kez ve sonra harfler haline 0, 1, 2, 3. Bu, switch- casemaddelerinde yer tasarrufu sağlar .
  • circshiftTek harfli anonim işlev olarak tanımlamak , iki kez kullanıldığı için yerden tasarruf sağlar.
  • Yana Doluşur '0've '1'karakterler (ASCII kodları 48ve 49), deyim D=char(97-D)arasındaki ters karşılık gelir '0've '1'değerler. Bunun 97yukarıda belirtilenlerle hiçbir ilgisi olmadığını unutmayın .
  • Transpozisyon 'yerine kompleks-konjugat transpozisyon kullanılır .'.

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 bayt

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

biçimlendirilmiş:

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&({::)))

biçimlendirilmiş:

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.

Misal

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

Giriş esnekliğini tamamen kullanarak, 2 dizi parametresi ile adlandırılmış bir işlev.

  • İlk parametre, 7 bit karakter kodlarına karşılık gelen bayt dizisi
  • İkinci parametre, 'F', 'L', 'R', 'U' -> 70, 76, 82, 85 ascii karakterlerine karşılık gelen bayt dizisi

İşlev, '1' ve '0' dan oluşan bir karakter dizesi döndürür

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

İçin f("b", "rfu") çeviri örneğiF([98],[82,70,85]) , sonuç0111001

Not karakter dizeleri javascript çok daha uzun! Bayt sayısı 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('')

Örnek F("b", "RFU") , sonuç 0111001yine


0

Ruby, 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}}

Yeterince açıksözlü. Döngüler içindeki karakterlerden oluşur sve bunlardan herhangi biri için bir eylem gerçekleştirir.


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

Yaklaşımdaki benim pyth cevap benzer: Ben azaltma kullanarak yinelenen talimat dizesinin değerine dayalı tüm dizeleri ve dizin içine bir dizin oluşturmak.

Kullanım Alanları:

0  ->  Rotate left
1  ->  Rotate right
2  ->  Reverse order
3  ->  Invert bits
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.