Bir Rus şifreleme standardının çok yapılandırıldığını kanıtlamak


92

Bu zorluğun amacı, seçtiğiniz fonksiyonda , aşağıdaki fonksiyonun imkansız bir şekilde kısa bir uygulamasını bulmaktır p. İşte bunu uygulayan C kodu ( çıktılarını da basan bu TIO bağlantısına bakın ) ve onu içeren bir wikipedia sayfası .

unsigned char pi[] = {
    252,238,221,17,207,110,49,22,251,196,250,218,35,197,4,77,
    233,119,240,219,147,46,153,186,23,54,241,187,20,205,95,193,
    249,24,101,90,226,92,239,33,129,28,60,66,139,1,142,79,
    5,132,2,174,227,106,143,160,6,11,237,152,127,212,211,31,
    235,52,44,81,234,200,72,171,242,42,104,162,253,58,206,204,
    181,112,14,86,8,12,118,18,191,114,19,71,156,183,93,135,
    21,161,150,41,16,123,154,199,243,145,120,111,157,158,178,177,
    50,117,25,61,255,53,138,126,109,84,198,128,195,189,13,87,
    223,245,36,169,62,168,67,201,215,121,214,246,124,34,185,3,
    224,15,236,222,122,148,176,188,220,232,40,80,78,51,10,74,
    167,151,96,115,30,0,98,68,26,184,56,130,100,159,38,65,
    173,69,70,146,39,94,85,47,140,163,165,125,105,213,149,59,
    7,88,179,64,134,172,29,247,48,55,107,228,136,217,231,137,
    225,27,131,73,76,63,248,254,141,83,170,144,202,216,133,97,
    32,113,103,164,45,43,9,91,203,155,37,208,190,229,108,82,
    89,166,116,210,230,244,180,192,209,102,175,194,57,75,99,182,
};

unsigned char p(unsigned char x) {
     return pi[x];
}

Nedir p

pİki şifreleme standardı olan yani hash işlevi Streebog ve blok şifreleme Kuznyechik'in bir bileşenidir . Olarak bu makalede (ISO toplantı sırasında), bu algoritmaların tasarımcıları dizi oluşturulan iddia pirastgele 8 bit permütasyon seçerek.

"İmkansız" uygulamalar

Orada 256!21684 8 bit üzerinde permütasyon. Bu nedenle, verilen rastgele bir permütasyon için, onu uygulayan bir programın 1683 bitten daha azına ihtiyaç duyması beklenmeyecektir.

Bununla birlikte, aşağıda sıralanan C programı gibi anormal derecede çok sayıda küçük uygulama bulduk ( burada listelediğimiz ).

p(x){unsigned char*k="@`rFTDVbpPBvdtfR@\xacp?\xe2>4\xa6\xe9{z\xe3q5\xa7\xe8",l=0,b=17;while(--l&&x^1)x=2*x^x/128*285;return l%b?k[l%b]^k[b+l/b]^b:k[l/b]^188;}

sadece 158 karakter içeriyor ve bu nedenle 1264 bit'e sığıyor. İşe yaradığını görmek için buraya tıklayın .

"İmkansız" bir kısa uygulamadan bahsediyoruz, çünkü eğer izin rastgele bir sürecin çıktısı olsaydı (tasarımcıları tarafından iddia edildiği gibi), o zaman bu kısa bir program olmazdı ( daha fazla bilgi için bu sayfaya bakınız).

Referans uygulaması

Önceki C kodunun daha okunabilir bir versiyonu:

unsigned char p(unsigned char x){
     unsigned char
         s[]={1,221,146,79,147,153,11,68,214,215,78,220,152,10,69},
         k[]={0,32,50,6,20,4,22,34,48,16,2,54,36,52,38,18,0};
     if(x != 0) {
         unsigned char l=1, a=2;
         while(a!=x) {
             a=(a<<1)^(a>>7)*29;
             l++;
         }
         unsigned char i = l % 17, j = l / 17;
         if (i != 0) return 252^k[i]^s[j];
         else return 252^k[j];
     }
     else return 252;
}

Masa k şekildedir k[x] = L(16-x)burada, Lanlamında doğrusal L(x^y)==L(x)^L(y)C'de olduğu gibi, ve ^XOR belirtmektedir. Ancak, uygulamamızı kısaltmak için bu mülkten yararlanamadık. sBasit bir uygulamaya izin verecek herhangi bir yapının farkında değiliz - çıktısı her zaman alt alandadır, yani s[x]16=s[x] üssünün sonlu alanda yapıldığı s [ x ] 16 = s [ x ] . Elbette, sbulmanız gereken daha basit bir ifadeyi kullanmakta kesinlikle özgürsünüz !

While döngüsü, sonlu alanda ayrık bir logaritmanın 256 elemanla değerlendirilmesine karşılık gelir. Basit bir kaba kuvvet arama yoluyla çalışır: kukla değişken asonlu alanın bir jeneratörü olarak ayarlanır ve sonuç eşit olana kadar bu jeneratör ile çarpılır x. Durum söz konusu olduğunda, biz layrık kütüğümüz var x. Bu işlev 0 ile tanımlanmaz, dolayısıyla ififadeye karşılık gelen özel durum .

Jeneratör ile çarpma ile çarpılması olarak görülebilir X in F2[X] , sonra polinom modulo azalır X8+X4+X3+X2+1 . Rolüunsigned chardeğişkenina8 bit üzerinde kalmasınısağlamaktır. Alternatif olarak,a=(a<<1)^(a>>7)*(256^29)bu durumdaabirint(veya başka bir tamsayı türü) olabiliriz. Öte yandan,1'e eşitl=1,a=2olduğul=255zamanihtiyacımızolandan başlamak gereklix.

Özellikleriyle ilgili daha fazla ayrıntı , önceki kısa uygulamayı elde etmek için optimizasyonlarımızın çoğunu içeren bir yazı ile, makalemizde psunulmuştur .

kurallar

İşlevi p1683 bitin altında uygulayan bir program önerin . Program ne kadar kısaysa, belirli bir dil için o kadar anormal olan o kadar kısa olur. Diliniz Kuznyechik, Streebog veya pyerleşik bir dilde ise, bunları kullanamazsınız.

En iyi uygulamayı belirlemek için kullandığımız metrik, bayt cinsinden program uzunluğu. Akademik uzunluğumuzda bit uzunluğunu kullanıyoruz, ancak sadelik uğruna burada baytlara bağlıyız.

Dil fonksiyonu, argüman veya çıkış net bir fikri yoksa, kodlama tanımlamak için size kalmış, ancak değer kodlama gibi hileler pi[x]olarak xaçıkça yasaklanmıştır.

Bu konudaki bulgularımızı içeren bir araştırma makalesi hazırladık. Bu kullanılabilir burada . Ancak, bilimsel bir mekanda yayınlanması durumunda, en iyi uygulamaların yazarlarını memnuniyetle kabul edeceğiz.

Bu arada, bu soruyu hazırlarken yardımları için xnor'a teşekkürler!


12
Umarım birileri Tohumda bir cevap sunar.
Robin Ryder

6
Benzer şekilde, örneğin, beyin tıkanıklığı kodu, eğer boşluğu yoksa, karakter başına 3 bit olarak puanlanabilir mi? Ve 1683 bits at mostkatı bir kısıtlama [sic?] Veya amaç mı?
biri

31
Eğer permütasyon (tasarımcıları tarafından iddia edildiği gibi) rastgele bir sürecin çıktısı olsaydı, o zaman bu kısa bir program olmazdı ” Ben buna katılmıyorum (zorluk için önemli olmasa da). Eğer rastgele bir sürecin çıktısı olsaydı , böyle bir programın olması muhtemel değildi; ya da bulmak zor olurdu
Luis Mendo

8
@Grimy O zaman bu kısa olmayacak bir program kavramsal bir programdır (programlama değil). Terimlerinizi kullanarak, programlama dünyasına değil, tamamen matematik dünyasına aittir
Luis Mendo

7
Çoktan farkına varılmış olabilir, ancak şu durumda: yalnızca 8 farklı değerle sonuçlanır: 1 , 10 , 68 , 79 , 146 , 153 , 220 , 221 ( i = 1 ile başlayan ve s varsayarak 0 = 0 ). sben XOR sben-11,10,68,79,146,153,220,221ben=1s0=0
Arnauld

Yanıtlar:


35

AMD64 Assembly (78 bayt veya 624 bit makine kodu)

uint8_t SubByte (uint8_t x) {
    uint8_ty, z;
    uint8_t s [] =
      {1,221,146,79,147,153,11,68,214,215,78,220,152,10,69};

    uint8_t k [] =
      {0,32,50,6,20,4,22,34,48,16,2,54,36,52,38,18,0};

    eğer (x) {
      (y = z = 1; (y = (y << 1) ^ ((y >> 7) * 29))! = x; z ++);
      x = (z% 17);
      z = (z / 17);
      x = (x)? k [x] ^ s [z]: k [z];
    }
    dönüş x ^ 252;
}

64 bit x86 derlemesi

    ; AMD64 derlemesinin 78 baytı
    ; odzhan
    bitler 64

    % ifndef BIN
      genel SubBytex
    % endif

SubBytex:
    mov al, 252
    jecxz L2; eğer (x) {
    L0'ı ara
k:
    db 0xfc, 0xdc, 0xce, 0xfa, 0xe8, 0xf8, 0xea, 0xde, 
    db 0xcc, 0xec, 0xfe, 0xca, 0xd8, 0xc8, 0xda, 0xee, 0xfc
s:
    db 0x01, 0xdd, 0x92, 0x4f, 0x93, 0x99, 0x0b, 0x44, 
    db 0xd6, 0xd7, 0x4e, 0xdc, 0x98, 0x0a, 0x45
L0:
    pop rbx
    mov al, 1; y = 1
    cdq; z = 0
L1:
    dl; z ++
    al al al; y = y + y
    jnc $ + 4; taşıma yoksa XOR atla
    xor al, 29;
    cmp al, cl; eğer (y! = x) L1'e giderse
    jne L1    

    xchg eax, edx; eax = z
    cdq; edx = 0
    mov cl, 17; al = z / 17, dl = z% 17
    div ecx

    mov cl, [rbx + rax + 17]; cl = s [z]
    xlatb; al = k [z]
    test dl, dl; eğer (x == 0) L2 ye gidersek
    jz L2
    xchg eax, edx; al = x
    xlatb; al = k [x]
    xor al, cl; al ^ = s [z]
L2:
    çürümek

Demonte 64 bit kod

00000000 B0FC mov al, 0xfc
00000002 67E348 jecxz 0x4d
00000005 E820000000 arama qword 0x2a
; k [] = 0xfc, 0xdc, 0xce, 0xfa, 0xe8, 0xf8, 0xea, 0xde
; 0xcc, 0xec, 0xfe, 0xca, 0xd8, 0xc8, 0xda, 0xee, 0xfc
; s [] = 0x01, 0xdd, 0x92, 0x4f, 0x93, 0x99, 0x0b, 0x44,
; 0xd6, 0xd7, 0x4e, 0xdc, 0x98, 0x0a, 0x45
0000002A 5B pop rbx
0000002B B001 mov al, 0x1
0000002D 99 cdq
0000002E FEC2 inc dl
00000030 00C0 al al, al
00000032 7302 jnc 0x36
00000034 341D xor al, 0x1d
00000036 38C8 cmp al, cl
00000038 75F4 jnz 0x2e
0000003A 92 xchg eax, edx
0000003B 99 cdq
0000003C B111 mov cl, 0x11
0000003E F7F1 div ecx
00000040 8A4C0311 mov cl, [rbx + rax + 0x11]
00000044 D7 xlatb
00000045 84D2 testi dl, dl
00000047 7404 jz 0x4d
00000049 92 xchg eax, edx
0000004A D7 xlatb
0000004B 30C8 veya daha fazla, cl
0000004D C3 ret

32 bit x86 derlemesi

    ; 72 bayt x86 derlemesi
    ; odzhan
    32 bit

    % ifndef BIN
      genel SubBytex
      global _SubBytex
    % endif

SubBytex:
_SubBytex:
    mov al, 252
    jecxz L2; eğer (x) {
    L0'ı ara
k:
    db 0xfc, 0xdc, 0xce, 0xfa, 0xe8, 0xf8, 0xea, 0xde, 
    db 0xcc, 0xec, 0xfe, 0xca, 0xd8, 0xc8, 0xda, 0xee, 0xfc
s:
    db 0x01, 0xdd, 0x92, 0x4f, 0x93, 0x99, 0x0b, 0x44, 
    db 0xd6, 0xd7, 0x4e, 0xdc, 0x98, 0x0a, 0x45
L0:
    pop ebx
    mov al, 1; y = 1
    cdq; z = 0
L1:
    inc edx; z ++
    al al al; y = y + y
    jnc $ + 4; taşıma yoksa XOR atla
    xor al, 29;
    cmp al, cl; eğer (y! = x) L1'e giderse
    jne L1    
    xchg eax, edx; al = z
    aam 17; al | x = z% 17, ah | z = z / 17
    mov cl, ah; cl = z
    cmove eax, ecx; eğer (x == 0) al = z baska al = x
    xlatb; al = k [z] veya k [x]
    jz L2; eğer (x == 0) L2 ye gidersek
    xor al, [ebx + ecx + 17]; k [x] ^ = k [z]
L2:
    çürümek

Demonte 32 bit kod

00000000 B0FC mov al, 0xfc
00000002 E345 jecxz 0x49
00000004 E820000000 arama sözcüğü 0x29
; k [] = 0xfc, 0xdc, 0xce, 0xfa, 0xe8, 0xf8, 0xea, 0xde
; 0xcc, 0xec, 0xfe, 0xca, 0xd8, 0xc8, 0xda, 0xee, 0xfc
; s [] = 0x01, 0xdd, 0x92, 0x4f, 0x93, 0x99, 0x0b, 0x44,
; 0xd6, 0xd7, 0x4e, 0xdc, 0x98, 0x0a, 0x45
00000029 5B pop ebx
0000002A B001 mov al, 0x1
0000002C 99 cdq
0000002D 42 inc edx
0000002E 00C0 al al, al
00000030 7302 jnc 0x34
00000032 341D xor al, 0x1d
00000034 38C8 cmp al, cl
00000036 75F5 jnz 0x2d
00000038 92 xchg eax, edx
00000039 D411, 0x11
0000003B 88E1 mov cl, ah
0000003D 0F44C1 cmovz eax, ekx
00000040 D7 xlatb
00000041 7404 jz 0x47
00000043 32440B11 xor al, [ebx + ecx + 0x11]
00000047 C3 ret

1
Güzel cevap! OP bit sayısı aradığından, bu (85 bayt) , bayt başına 8 bit kullanan 680 bit veya bayt başına 7 bit kullanan 595 bit (tüm karakterler ASCII olduğundan mümkün). Daha da kısıtlayıcı bir karakter setine sıkıştırdıysanız, muhtemelen kısalırsınız.
Cullub

1
PPCG'ye Hoşgeldiniz; güzel ilk çözüm.
Shaggy

9
@Cullub Demek istediğim, bu cevaptaki kod sadece derlenen C / Assembler'dı, bu yüzden bayt sayısı verilen kodun değil derlenen kodun kodu. Ve bu ASCII değil.
ArBo

7
Sadece açıklama için, 84 byte, montajdan sonra makine kodunun büyüklüğüdür? Eğer öyleyse, başlığın bunun bir montaj cevabı yerine bir makine kodu cevabı olduğunu yansıtacak şekilde güncellenmesi gerekir.
Patates44

1
Ve BTW, standart bir arama sözleşmesi kullanmak zorunda değilsiniz; RBX'in çağrı engelli olduğu özel bir kongre kullanabilirsiniz, böylece push / pop için 2 bayt tasarruf sağlar. (Ve burada uint8_t, JRCXZ için arpların 64-bit'e sıfırlandığı yerler). Ayrıca, pozisyona bağlı kod yazarsanız, tablo adresini mov ebx, imm326-byte call/ yerine 5-byte olan bir sicil içine koyabilirsiniz pop. Ya da bir disp32girişi olarak kullanın mov al, [table + rax], ama zaten iki xlatbve bir tane olduğundan bu kaybolabilir mov. Call + pop shellcode numarası 7-byte RIP-göreli LEA'yı kazandıktan sonra verilerle kazanır ret.
Peter Cordes

23

CJam ,72 67 66 63 bayt

ri{_2md142*^}es*]2#~Hmd{5\}e|Fm2b"Ý0$&Ü™ÖD�’
˜×EO“N".*Lts:^i

es* Geçerli zaman damgasında bir şeyi tekrarlar, bu büyük bir sayıdır ve bitirmesi çok uzun sürecektir.

Aslında test edilebilir versiyon, 64 bayt:

ri{_2md142*^}256*]2#~Hmd{5\}e|Fm2b"Ý0$&Ü™ÖD�’
˜×EO“N".*Lts:^i
00000000: 7269 7b5f 326d 6431 3432 2a5e 7d32 3536  ri{_2md142*^}256
00000010: 2a5d 3223 7e48 6d64 7b35 5c7d 657c 466d  *]2#~Hmd{5\}e|Fm
00000020: 3262 22dd 3024 2612 dc99 d644 0092 0b0a  2b".0$&....D....
00000030: 98d7 454f 934e 0122 2e2a 4c74 733a 5e69  ..EO.N.".*Lts:^i

Çevrimiçi deneyin!

Hepsini çevrimiçi deneyin!

(Bir Linux makine) bu kodu çalıştırmak için, satır eklemek gerekir en_US.ISO-8859-1 ISO-8859-1içine /etc/locale.genve çalıştırın locale-gen. Sonra kullanabilirsiniz:

LANG=en_US.ISO-8859-1 java -jar cjam.jar <source file>

Veya bu eşdeğer 72 bayt UTF-8 sürümünü deneyebilirsiniz:

00000000: 7269 7b5f 326d 6431 3432 2a5e 7d32 3536  ri{_2md142*^}256
00000010: 2a5d 3223 7e48 6d64 7b35 5c7d 657c 466d  *]2#~Hmd{5\}e|Fm
00000020: 3262 22c3 9d30 2426 12c3 9cc2 99c3 9644  2b"..0$&.......D
00000030: 00c2 920b 0ac2 98c3 9745 4fc2 934e 0122  .........EO..N."
00000040: 2e2a 4c74 733a 5e69                      .*Lts:^i

açıklama

ri               e# Read input.
{_2md142*^}      e# Copy and divide by 2. If remainder is 1, xor 142.
es*]             e# Repeat a lot of times and wrap all results in an array.
2#               e# Find the first occurrence of 2, -1 if not found.
~                e# Increment and negate.
Hmd              e# Divmod 17. Both the quotient and remainder would be negated.
{5\}e|           e# If remainder = 0, return 5, quotient instead.
Fm2b             e# Subtract 15 from the remainder and expand in base 2.
                 e# In CJam, base conversion only applies to the absolute value.
"...".*          e# Filter 221, 48, 36, 38, 18 by the bits.
                 e# 221, the characters after 18
                 e#   and 18 itself in case quotient - 15 = -15 won't change.
Lt               e# Remove the item s[quotient] xor 220.
                 e# Quotient is 0, 5 or a negative integer from the end,
                 e#   which doesn't overlap with the previously filtered items.
s                e# Flatten, because some characters become strings after the process.
:^i              e# Reduce by xor and make sure the result is an integer.

Dizedeki karakterler:

  • 221. Aşağıya bakınız.
  • 48, 36, 38, 18. Söz konusu L'nin özelliklerine dayanarak k'nın doğrusal ayrışması.
  • 220'de, yalnızca k dizisi kullanıldığında dizinin s'nin doldurma değeri.
  • Dizinin başlangıcındaki 221 olan son öğe veya ters çevrilmeden önceki ilk öğe hariç, dizi x veya 220 ters.

Güç ayarında ne yapardın? PS Muhtemelen sonlu saha işlemini tersine çevirme hilesini çalacağım. Çok temiz.
Peter Taylor

@PeterTaylor En basit sıralamaya sahip [48 36 38 18] güç grubunu (veya tersini) kullanarak dizi k elde edebilir ve her birini xor azaltabilirsiniz. Ancak bu soruda şu ana kadar kullanılan golf dillerinde sadece 05AB1E doğru sıralamaya sahipti. Jelly ve Stax görünüşte anlaşılır olması gerektiği hakkında farklı fikirleri vardı.
jimmy23013

Şu anda 05AB1E'ye verdiğiniz cevabı golf oynuyorum. Dizeniz için tamsayı değerleri nelerdir "Ý0$&Ü™ÖD�’\n˜×EO“N"?
Kevin Cruijssen

@KevinCruijssen Ne anlama geldiklerini veya sayısal değerlerini (on altılı çöplükten görebileceğiniz) mi soruyorsunuz?
jimmy23013

@ jimmy23013 Ah, elbette .. Onaltılık çöplüğü unuttum ..
Kevin Cruijssen

19

Jöle 71 59 bayt

H^142ƊHḂ?Ƭi2d17U⁸⁴;$Ḣ?$CµṪạ⁴B¬T;;6ị“Œ0$&ØŀWð⁺Ṫ\ḢĠVı⁻¹]°Ẇ‘^/

Çevrimiçi deneyin!

Tüm olasılıkları doğrula

Şimdi jimmy23013'ün akıllı CJam cevabının elden geçirilmiş bir versiyonunu kullanarak yeniden yazıldı bu yüzden onu da mutlaka unutma! Yalnızca 472 bit kullanır (saf yaklaşımın% 28,0'ı). @ jimmy23013 ayrıca bir bayt daha kurtardı!

açıklama

Aşama 1

         Ƭ        | Repeat the following until no new entries:
       Ḃ?         | - If odd:
     Ɗ            |   - Then following as a monad:
H                 |     - Halve
 ^142             |     - Xor 142
      H           |   - Else: Halve
          i2      | Index of 2 in this list

2. aşama

d17           | Divmod 17
          $   | Following as a monad:
   U          | - Reverse order
        Ḣ?    | - If head (remainder from divmod) non-zero:
    ⁸         |   - Then: left argument [quotient, remainder]
     ⁴;$      |   - Else: [16, quotient]
           C  | Complement (1 minus)
            µ | Start a new monadic chain

Sahne 3

Ṫ                   | Tail (Complement of remainder or quotient from stage 2)
 ạ⁴                 | Absolute difference from 16
   B                | Convert to binary
    ¬               | Not
     T              | Indices of true values
      ;             | Concatenate (to the other value from stage 2)
       ;6           | Concatenate to 6
         ị“Œ...Ẇ‘   | Index into [19,48,36,38,18,238,87,24,138,206,92,197,196,86,25,139,129,93,128,207]
                 ^/ | Reduce using xor

Orijinal yaklaşım

Jelly , 71 66 bayt

H^142ƊHḂ?Ƭi2d:j@“ÐḌ‘ɗ%?17ị"“p?Ä>4ɼḋ{zẉq5ʂċ¡Ḅ“`rFTDVbpPBvdtfR@‘^ƒ17

Çevrimiçi deneyin!

Tüm olasılıkları doğrula

Tek bir argüman alan ve tek bir argüman alan ve ilgili değerini veren tam bir program pi[x]. Bu, 536 bittir, yani pi'nin saf depolanmasının üçte biri altında.

Bulmak için bir yöntemi kullanarak 3 bayt Kaydedilen lgelen jimmy23013 en CJam cevap böylece bir çok upvote emin olun!

açıklama

Aşama 1

         Ƭ        | Repeat the following until no new entries:
       Ḃ?         | - If odd:
     Ɗ            |   - Then following as a monad:
H                 |     - Halve
 ^142             |     - Xor 142
      H           |   - Else: Halve
          i2      | Index of 2 in this list

2. aşama

         %?17  | If not divisible by 17
d              | - Then divmod 17
        ɗ      | - Else following as a dyad (using 17 as right argument)
 :             |   - Integer divide by 17
  j@“ÐḌ‘       |   - Join the list 15,173 by the quotient

Sahne 3

ị"“p...Ḅ“`...@‘     | Index into two compressed lists of integers using the output from stage 2 (separate list for each output from stage 2). The third output from stage 2 will be left untouched
               ^ƒ17 | Finally reduce using Xor and 17 as the first argument


15

C (gcc) , 157 148 140 139 bayt

C örneği üzerinde mütevazı gelişme.

l,b=17,*k=L"@`rFTDVbpPBvdtfR@";p(x){for(l=256;--l*~-x;)x=2*x^x/128*285;return l%b?k[l%b]^"\xcer?\4@6\xc8\t{|\3q5\xc7\n"[l/b]-b:k[l/b]^188;}

Çevrimiçi deneyin!

C (gcc) , 150 142 127 126 bayt

Bu, gcc ve x86 ve UTF-8 tuhaflıklarına bağlıdır.

l,*k=L"@`rFTDVbpPBvdtfR@";p(x){for(l=256;--l*~-x;)x=2*x^x/128*285;x=l%17?k[l%17]^L"½a.ó/%·øjkò`$¶ù"[l/17]:k[l/17]^188;}

Çevrimiçi deneyin!

@XavierBonnetain için -1 ve daha az tanımsız davranış için teşekkürler.


10

05AB1E , 101 100 98 97 95 94 bayt

U•α">η≠ε∍$<Θγ\&@(Σα•₅вV₁[<ÐX*Q#X·₁%Xžy÷Ƶ¹*₁%^₁%U}D17©%DĀiYsès®÷•¾#kôlb¸ù,-ó"a·ú•₅вë\Ƶ∞s®÷Y}sè^

@Grimy sayesinde -3 bayt .

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

Xavier Bonnetain'in C işlevi (1106 bit sürümü) buradan , 3 geliştirmeden tasarruf etmek için C cevabında @ceilingcat ile aynı iyileştirme yapıldı , bu yüzden onu oyladığınızdan emin olun!

U                    # Store the (implicit) input in variable `X`
•α">η≠ε∍$<Θγ\&@(Σα• "# Push compressed integer 20576992798525946719126649319401629993024
 ₅в                  # Converted to base-255 as list:
                     #  [64,96,114,70,84,68,86,98,112,80,66,118,100,116,102,82,64]
   V                 # Pop and store this list in variable `Y`
                    # Push `i` = 256
 [                   # Start an infinite loop:
  <                  #  Decrease `i` by 1
   Ð                 #  Triplicate `i`
    X*Q              #  If `i` multiplied by `X` is equal to `i` (i==0 or X==1):
       #             #   Stop the infinite loop
  X·₁%               #  Calculate double(`X`) modulo-256
                     #  (NOTE: all the modulo-256 are to mimic an unsigned char in C)
  Xžy÷               #  Calculate `X` integer-divided by builtin integer 128,
      Ƶ¹*            #  multiplied by compressed integer 285,
         ₁%          #  modulo-256
  ^                  #  Bitwise-XOR those together
   ₁%                #  And take modulo-256 again
  U                  #  Then pop and store it as new `X`
 }D                  # After the loop: Duplicate the resulting `i`
   17©               # Push 17 (and store it in variable `®` without popping)
      %              # Calculate `i` modulo-17
       D             # Duplicate it
        Āi           # If it's NOT 0:
          Ysè        #  Index the duplicated `i` modulo-17 into list `Y`
          s®÷        #  Calculate `i` integer-divided by 17
          •¾#kôlb¸ù,-ó"a·ú•
                    "#  Push compressed integer 930891775969900394811589640717060184
           ₅в        #  Converted to base-255 as list:
                     #   [189,97,46,243,47,37,183,248,106,107,242,96,36,182,249]
         ë           # Else (`i` == 0):
          \          #  Discard the duplicated `i` modulo-17, since we don't need it
          Ƶ∞         #  Push compressed integer 188
          s®÷        #  Calculate `i` integer-divided by 17
          Y          #  Push list `Y`
         }s          # After the if-else: swap the integer and list on the stack
           è         # And index the `i` modulo/integer-divided by 17 into the list
            ^        # Then Bitwise-XOR the top two together
                     # (after which the top of the stack is output implicitly as result)

Benim bu 05AB1E ucu bakın (bölümler büyük tamsayılar sıkıştırmak nasıl? Ve tamsayı listeleri sıkıştırmak nasıl? ) Anlamak için •α">η≠ε∍$<Θγ\&@(Σα•ise 20576992798525946719126649319401629993024; •α">η≠ε∍$<Θγ\&@(Σα•₅вolduğu [64,96,114,70,84,68,86,98,112,80,66,118,100,116,102,82,64]; Ƶ¹olduğu 285; •¾#kôlb¸ù,-ó"a·ú•olduğu 930891775969900394811589640717060184; •¾#kôlb¸ù,-ó"a·ú•₅вolduğu [189,97,46,243,47,37,183,248,106,107,242,96,36,182,249]; ve Ƶ∞olduğu 188.


@Grimy Sıkıştırılmış tamsayı listeleriyle bu tür bir golfü her zaman unuttum .. (Not: Her iki tarafın da yorumlarında 'içeren' kodunu çevreleyebilirsiniz. Yani '' yerine '' 'kod' kodu ''.)
Kevin Cruijssen

Hata, karışık biçimlendirme için üzgünüm. Tepkilerin iki katına çıkmasını biliyorum, ancak sıkıştırılmış listenin içinde bir tepesinin olduğunu anlamadım. Ayrıca: s^=> ^(XOR değişmelidir). Aslında, s^_aynısı değil Qmi?
Grimy

@Grimy Teşekkürler! Gerçekten haklısın. Aşağıdaki üç şeyden biri döngü çıkmak için truthy ise biz temelde kontrol edin: i==0 || X==0 || X==1.
Kevin Cruijssen

10

Stax , 65 64 62 59 58 bayt

ç∙¼≥2▼Uó╤áπ╙º┐╩♫∟öv◘≥δ♦Θ╫»─kRWÑâBG")≥ö0╥kƒg┬^S ΔrΩ►╣Wü Ü╕║

Koş ve hata ayıkla

Ne yazık ki, bu program dahili olarak kullanım dışı bazı stax talimatlarını kullanan bazı talimatlar kullanır. Sadece uygulamalarını güncellemeyi unuttum. Bu, bazı sahte uyarıların görünmesine neden olur, ancak sonuçlar yine de doğrudur.

Bu jimmy23013'ün mükemmel cevabından ilham alıyor . Bazı parçalar staks daha iyi uyacak şekilde değiştirildi.

Yazdırılabilir ASCII'de yazılmış Stax programları, yalnızca yazdırılabilir ASCII karakterleri olduğundan, bayt başına 1 bitten biraz tasarruf sağlayan alternatif bir gösterime sahiptir.

İşte yorum ile "okunabilirlik" için biçimlendirilmiş bu programın ascii gösterimi.

{                       begin block
  2|%142*S              given n, calculate (n/2)^(n%2*142)
                         - this seems to be the inverse of the operation in the while loop
gu                      use block to generate distinct values until duplicate is found
                         - starting from the input; result will be an array of generated values
2I^                     1-based index of 2 in the generated values
17|%                    divmod 17
c{Us}?                  if the remainder is zero, then use (-1, quotient) instead
~                       push the top of the main stack to the input stack for later use
"i1{%oBTq\z^7pSt+cS4"   ascii string literal; will be transformed into a variant of `s`
./o{H|EF                interpret ascii codes as base-94 integer
                         - this is tolerant of digits that exceed the base
                        then encode big constant as into base 222 digits
                         - this produces an array similar to s
                         - 0 has been appended, and all elements xor 220
@                       use the quotient to index into this array
"jr+R"!                 packed integer array literal [18, 38, 36, 48]
F                       for each, execute the rest of the program
  ;                     peek from the input array, stored earlier
  v                     decrement
  i:@                   get the i-th bit where i is the iteration index 0..3
  *                     multiply the bit by value from the array literal
  S                     xor with result so far
                        after the loop, the top of the stack is printed implicitly

Bunu çalıştır

Tüm girişler için çalıştırılacak modifiye edilmiş versiyon


Stax Sgüç ayarı için var. [18 38 36 48] güç setini alabilir, indeksleyebilir ve xor ile azaltabilirsiniz. (
Stax'i

Stax'ın Soperatör tarafından üretilen altkümeler için sipariş vermesi, bunun çalışması için doğru sırada olmadığını düşünüyorum. örneğin "abc"SJ(boşluklarla birleştirilen "abc" gücü) "ab abc ac b bc c" üretir.
özyinelemeli

8

Python 3 , 151 bayt

f=lambda x,l=255,k=b'@`rFTDVbpPBvdtfR@':f(x*2^x//128*285,l-1)if~-x*l else[k[l%17]^(0x450a98dc4ed7d6440b99934f92dd01>>l//17*8&255),k[l//17]][l%17<1]^188

Çevrimiçi deneyin!

Permütasyonu uygulayan bir fonksiyon. Kod yalnızca 7 bit ASCII karakterlerini kullanır.

Yazdırılabilir aralığa kkaydırılan Python 3 bytestring olarak kodlar ^64. Buna karşılık, ssayısal bir sabitin temel 256 basamağı olarak kodlanır ve rakamlar olarak çıkarılır [number]>>[shift]*8&255. Bu kodlamadan daha kısaydıs gerekli olan kaçış karakterlerinin sayısı nedeniyle en ^160aza indirmek için optimal bir kayma olsa bile, bir dizgede .

Ayrık log hesaplaması geriye doğru yapılır. Güncelleme x=x*2^x//128*285, kimliğe ulaşana kadar, oluşturucu ile çarpmayı simüle ederek döngüsel grupta ileriye doğru döngü yapar x=1. Ayrık kütüğü başlayarak l=255(döngü uzunluğu) ve her yinelemede azaltıyoruz. x=0Davayı ele almak ve sonsuza dek döngü yapmamak için l=0, x=0haritayı l=0belirtilen şekilde yapan ne zaman sona ereriz.


Python 2 güzel bytestrings olmadığı için kaybeder, bu yüzden yapmamız gerekir map(ord,...)(ArBo burada bir byte kaydetti). Tamsayılı bölme /yerine kullanmamızı sağlar //.

Python 2 , 156 bayt

f=lambda x,l=255,k=map(ord,'@`rFTDVbpPBvdtfR@'):f(x*2^x/128*285,l-1)if~-x*l else[k[l%17]^(0x450a98dc4ed7d6440b99934f92dd01>>l/17*8&255),k[l/17]][l%17<1]^188

Çevrimiçi deneyin!


7

JavaScript (ES6), 139 bayt

Node.js sürümüne benzer, ancak ASCII aralığının dışındaki karakterleri kullanma.

f=(x,l=256,b=17,k=i=>"@`rFTDVbpPBvdtfR@¬p?â>4¦é{zãq5§è".charCodeAt(i))=>--l*x^l?f(x+x^(x>>7)*285,l):l%b?k(l%b)^k(b+l/b)^b:k(l/b)^188

Çevrimiçi deneyin!


JavaScript (Node.js) ,  149  148 bayt

Xavier Bonnetain'in C uygulamasına dayanarak ( burada sunulmaktadır ).

f=(x,l=256,b=17,k=i=>Buffer("@`rFTDVbpPBvdtfR@,p?b>4&i{zcq5'h")[~~i]|3302528>>i-b&128)=>--l*x^l?f(x+x^(x>>7)*285,l):l%b?k(l%b)^k(b+l/b)^b:k(l/b)^188

Çevrimiçi deneyin!

Kodlama

Xavier'in orijinal cevabında, tablolar s[]ve k[]aşağıdaki dizgide saklanır:

"@`rFTDVbpPBvdtfR@\xacp?\xe2>4\xa6\xe9{z\xe3q5\xa7\xe8"
 \_______________/\__________________________________/
         k                         s

İlk 17 karakter ASCII gösterimidir k[i] XOR 64ve sonraki 15 karakter ASCII gösterimidir s[i-17] XOR 173veya s[i-17] XOR 64 XOR 17 XOR 252.

k[i] XOR 64s[i-17] XOR 173126128

İşte aldığımız şey:

original value : 172 112  63 226  62  52 166 233 123 122 227 113  53 167 232
subtract 128?  :   1   0   0   1   0   0   1   1   0   0   1   0   0   1   1
result         :  44 112  63  98  62  52  38 105 123 122  99 113  53  39 104
as ASCII       : "," "p" "?" "b" ">" "4" "&" "i" "{" "z" "c" "q" "5" "'" "h"

11001001100100125801

128

| 3302528 >> i - b & 128

s

Not: Bu sadece yukarıdaki cevaplarla ilgili olmayan bir nottur.

s

{1,11,79,146}

console.log(
  [ 0b0001, 0b1100, 0b1000, 0b0100, 0b1001, 0b1010, 0b0010, 0b0110,
    0b1110, 0b1111, 0b0101, 0b1101, 0b1011, 0b0011, 0b0111
  ].map(x =>
    [ 1, 11, 79, 146 ].reduce((p, c, i) =>
      p ^= x >> i & 1 && c,
      0
    )
  )
)

Çevrimiçi deneyin!



3

Python 3 , 182 bayt

def p(x,t=b'@`rFTDVbpPBvdtfR@\xacp?\xe2>4\xa6\xe9{z\xe3q5\xa7\xe8',l=255,d=17):
 if x<2:return 252-14*x
 while~-x:x=x*2^(x>>7)*285;l-=1
 return(188^t[l//d],d^t[l%d]^t[d+l//d])[l%d>0]

Çevrimiçi deneyin!

Python burada ilk ödülü kazanmak için gitmiyor, ama bu yine de iyi Python programının 10 bayt golf olduğunu burada .

Python 3 , 176 bayt

p=lambda x,l=255,t=b'@`rFTDVbpPBvdtfR@\xacp?\xe2>4\xa6\xe9{z\xe3q5\xa7\xe8',d=17:2>x<l>254and-14*x+252or(p(x*2^(x>>7)*285,l-1)if~-x else(188^t[l//d],d^t[l%d]^t[d+l//d])[l%d>0])

Çevrimiçi deneyin!

Bir lambda olarak, hala altı bayt daha kısa. Kullanmam gerekmekte zorlanıyor if... else, ancak 0'ın muhtemel bir cevabı olduğu için kısa devre için başka bir seçenek görmüyorum.

Python 3 , 173 bayt

p=lambda x,l=255,t=bytes('@`rFTDVbpPBvdtfR@¬p?â>4¦é{zãq5§è','l1'),d=17:2>x<l>254and-14*x+252or(p(x*2^(x>>7)*285,l-1)if~-x else(188^t[l//d],d^t[l%d]^t[d+l//d])[l%d>0])

Çevrimiçi deneyin!

Hatta bayt cinsinden daha kısa bile (bitlerden emin değilim, çünkü bu artık saf ASCII değil).


3 bayt kısa yerine değişmez karakter kullanılarak \x..çıkar
ovs


@ovs Teşekkürler! Muhtemelen bit sayısını bir miktar arttırır (hangisinin OP için en önemli olduğundan emin değilim), bu yüzden eski cevabımı da saklayacağım.
ArBo

2

Pas , 170 163 bayt

|mut x|{let(k,mut l)=(b"QqcWEUGsaASguewCQ\xacp?\xe2>4\xa6\xe9{z\xe3q5\xa7\xe8",255);while l*x!=l{x=2*x^x/128*285;l-=1}(if l%17>0{l+=289;k[l%17]}else{173})^k[l/17]}

Çevrimiçi deneyin!

Bu, C'deki çözümümün, x veya 17 gerektirmeyen, biraz farklı bir dize içeren bir bağlantı noktasıdır. Çözümlerin çoğunun "@` rFTDVbpPBvdtfR @ \ xacp? \ Xe2> 4 \ xa6 \ xe9 dizesini temel almasını bekliyorum. {z \ xe3q5 \ xa7 \ xe8 "de geliştirilebilir (sadece dizgiyi değiştirin, xor 17'yi ve 188 yerine xor 173'ü kaldırın).

Belirli şartlarda ekleyerek aramaları bir kaldırılır 17*17için lbiz (daha fazla veya daha az) KOL makine kodu çözeltisi içinde olduğu gibi.

Pasın tür çıkarımı ve kapamaları vardır, ancak atmaları (boolanlar için bile veya tamsayılar arasında bile) her zaman açıktır, mutasyonların işaretlenmesi gerekir, üçlü bir operatöre sahip değildir, tamsayı işlemleri, varsayılan olarak, taşma üzerine panik ve mutasyon işlemlerine sahip değildir ( l+=1) birimi döndürür. Kapaklar + haritalama hala oldukça ayrıntılı olduğundan tekrarlayıcılarla daha kısa bir çözüm elde etmeyi başaramadım.

Bu, Rust'ı golf oynamak için oldukça kötü bir seçim haline getiriyor. Bununla birlikte, özlü bir şekilde okunabilirliği ve güvenliği vurgulayan bir dilde bile, çok uzağız.

Güncelleme: manatwork'ün önerisinden anonim bir işlev kullandı.


1
Özyinelemeli olarak adlandırılması dışında, adsız işlevler / lambdalar kabul edilebilirdir, bu nedenle Başlığa geçebilir let p=ve sayılmaz. ;Anonim bir aramaya ihtiyaç duyulmadığından emin değilsiniz: Çevrimiçi deneyin! .
Manatwork

1

05AB1E , 74 bayt

₄FÐ;sÉiƵf^])2k>17‰Dθ_i¦16š}<(Rć16α2в≠ƶ0Kì6ª•5›@¾ÂÌLìÁŒ©.ðǝš«YWǝŠ•ƵŠвs<è.«^

@NickKennedy Limanı'nın ilk Jelly cevabı . @ Jimmy23013'ün CJam kullanıcısının doğrudan yanıtladığı bir bağlantı noktası üzerinde çalışıyordum , ancak zaten 78 byte'daydım ve hala bir hatayı düzeltmek zorunda kaldım, bu yüzden daha büyük olurdu. Yine de, bu kesinlikle hala biraz golf olabilir.

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

F              # Loop 1000 times:
  Ð             #  Triplicate the current value
                #  (which is the implicit input in the first iteration)
   ;            #  Halve it
    s           #  Swap to take the integer again
     Éi         #  If it's odd:
       Ƶf^      #   Bitwise-XOR it with compressed integer 142
]               # Close the if-statement and loop
 )              # Wrap all values on the stack into a list
  2k            # Get the 0-based index of 2 (or -1 if not found)
    >           # Increase it by 1 to make it 1-based (or 0 if not found)
     17        # Take the divmod-17 of this
Dθ_i    }       # If the remainder of the divmod is 0:
    ¦16š        #  Replace the quotient with 16
         <      # Decrease both values by 1
          (     # And then negate it
R               # Reverse the pair
 ć              # Extract head; push head and remainder-list
  16α           # Get the absolute difference between the head and 16
     2в         # Convert it to binary (as digit-list)
               # Invert booleans (0 becomes 1; 1 becomes 0)
        ƶ       # Multiply all by their 1-based indices
         0K     # And remove all 0s
           ì    # And prepend this in front of the remainder-list
            6ª  # And also append a trailing 6
5›@¾ÂÌLìÁŒ©.ðǝš«YWǝŠ•
                # Push compressed integer 29709448685778434533295690952203992295278432248
  ƵŠв           # Converted to base-239 as list:
                #  [19,48,36,38,18,238,87,24,138,206,92,197,196,86,25,139,129,93,128,207]
     s          # Swap to take the earlier created list again
      <         # Subtract each by 1 to make them 0-based
       è        # And index them into this list
.«^             # And finally reduce all values by bitwise XOR-ing them
                # (after which the result is output implicitly)

Benim bu 05AB1E ucu bakın (bölümler büyük tamsayılar sıkıştırmak nasıl? Ve tamsayı listeleri sıkıştırmak nasıl? ) Anlamak için Ƶfise 142; •5›@¾ÂÌLìÁŒ©.ðǝš«YWǝŠ•olduğu 29709448685778434533295690952203992295278432248, ƵŠolduğu 239; ve •5›@¾ÂÌLìÁŒ©.ðǝš«YWǝŠ•ƵŠвolduğu [19,48,36,38,18,238,87,24,138,206,92,197,196,86,25,139,129,93,128,207].

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.