Szyfr komputerowy

14

Wprowadzenie:

Mam wiele różnych szyfrów przechowywanych w dokumencie, który kiedyś skompilowałem jako dziecko, wybrałem kilka z tych, które moim zdaniem najlepiej nadawały się na wyzwania (niezbyt trywialne i niezbyt trudne) i przekształciłem je w wyzwania. Większość z nich wciąż znajduje się w piaskownicy i nie jestem jeszcze pewien, czy opublikuję je wszystkie, czy tylko kilka. Ale oto pierwszy z nich.


Szyfr komputerowy zaszyfruje dany tekst w „losowe” grupy znaków danego length. Jeśli taka grupa zawiera cyfrę, użyje tej cyfry do zaindeksowania własnej grupy dla zaszyfrowanego znaku. Jeśli w grupie nie ma żadnej cyfry, oznacza to, że użyto pierwszego znaku.

Załóżmy na przykład, że chcemy zaszyfrować tekst this is a computer ciphero podanej długości 5. Jest to potencjalny wynik (uwaga: liczby są indeksowane 1 w poniższym przykładzie):

t     h     i     s     i     s     a     c     o     m     p     u     t     e     r     c     i     p     h     e     r       (without spaces of course, but added as clarification)
qu5dt hprit k3iqb osyw2 jii2o m5uzs akiwb hwpc4 eoo3j muxer z4lpc 4lsuw 2tsmp eirkr r3rsi b5nvc vid2o dmh5p hrptj oeh2l 4ngrv   (without spaces of course, but added as clarification)

Weźmy kilka grup za przykłady, aby wyjaśnić, jak odszyfrować grupę:

  • qu5dt: Ta grupa zawiera cyfrę 5, więc (1-indeksowane) 5 charakter tej grupy jest znak używany dla tekstu rozszyfrować: t.
  • hprit: Ta grupa nie zawiera cyfry, więc pierwszy znak tej grupy jest używany w sposób dorozumiany do tekstu rozszyfrować: h.
  • osyw2: Te grupy zawiera cyfrę 2, więc (1-indeksowane) 2. charakter tej grupy jest znak używany dla tekstu rozszyfrować: s.

Wyzwanie:

Biorąc pod uwagę liczbę całkowitą lengthi ciąg word_to_encipher, wypisz losowy zaszyfrowany ciąg, jak opisano powyżej.

Musisz tylko wyszyfrować dane dane lengthi word_to_encipher, więc nie musisz również tworzyć programu / funkcji odszyfrowującej. Mogę jednak podjąć wyzwanie w ramach części 2 w celu odszyfrowania w przyszłości.

Zasady konkursu:

  • Możesz założyć, że lengthbędzie w zakresie [3,9].
  • Możesz założyć, że word_to_encipherbędzie zawierać tylko litery.
  • Możesz użyć zarówno wielkich, jak i wielkich liter (podaj, którego użyłeś w odpowiedzi).
  • Twoje dane wyjściowe, każda grupa i pozycje cyfr w grupie (jeśli są obecne) powinny być jednakowo losowe . Tak więc wszystkie losowe litery alfabetu mają taką samą szansę wystąpienia; pozycja zaszyfrowanej litery w każdej grupie ma taką samą szansę wystąpienia; a pozycja cyfry ma taką samą szansę wystąpienia (z wyjątkiem sytuacji, gdy jest to pierwszy znak i nie ma żadnej cyfry; i oczywiście nie może znajdować się w tej samej pozycji co zaszyfrowany znak).
  • Możesz także używać cyfr 0-indeksowanych zamiast 1-indeksowanych. Podaj, którego z dwóch użyłeś w swojej odpowiedzi.
  • Cyfra 1(lub 0indeksowana 0) nigdy nie będzie obecna na wyjściu. Dlatego b1ndhnie jest prawidłową grupą do szyfrowania znaku „b”. Jednak b4tbwjest ważne, gdzie 4enciphersb na 4. (1 indeksowane) pozycji, a pozostałe znakib ,t , wsą przypadkowe (który zawiera przypadkowo także b). Inne możliwe ważnych grup length5 do encipher znak „B”: abcd2, ab2de, babbk, hue5b, itd.

Główne zasady:

  • To jest , więc wygrywa najkrótsza odpowiedź w bajtach.
    Nie pozwól, aby języki gry w golfa zniechęcały Cię do publikowania odpowiedzi w językach niekodujących golfa. Spróbuj znaleźć możliwie najkrótszą odpowiedź na „dowolny” język programowania.
  • Do odpowiedzi mają zastosowanie standardowe reguły z domyślnymi regułami We / Wy , więc możesz używać STDIN / STDOUT, funkcji / metody z odpowiednimi parametrami i typem zwracanych, pełnych programów. Twoja decyzja.
  • Domyślne luki są zabronione.
  • Jeśli to możliwe, dodaj link z testem swojego kodu (tj. TIO ).
  • Zalecane jest również dodanie wyjaśnienia do odpowiedzi.

Przypadki testowe:

Input:
 Length:           5
 Word to encipher: thisisacomputercipher
Possible output:
 qu5dthpritk3iqbosyw2jii2om5uzsakiwbhwpc4eoo3jmuxerz4lpc4lsuw2tsmpeirkrr3rsib5nvcvid2odmh5phrptjoeh2l4ngrv

Input:
 Length:           8
 Word to encipher: test
Possible output:
 ewetng4o6smptebyo6ontsrbtxten3qk

Input:
 Length:           3
 Word to encipher: three
Possible output:
 tomv3h2rvege3le
Kevin Cruijssen
źródło
2
Co oznacza „mundur”
l4m2
@ l4m2 Że istnieje równa szansa dla dowolnego wyjścia. Tak więc wszystkie losowe litery alfabetu mają taką samą szansę wystąpienia; pozycja zaszyfrowanej litery w każdej grupie ma taką samą szansę wystąpienia; a pozycja cyfry ma taką samą szansę wystąpienia (z wyjątkiem sytuacji, gdy jest to pierwszy znak i nie ma żadnej cyfry, a także nie na tej samej pozycji co zaszyfrowany znak).
Kevin Cruijssen,
Więc abcd2, ab2de, babbkwszystkie są takie same? Czy jest również b1akkważny?
l4m2
@ l4m2 Tak, wszystkie trzy są możliwymi wyjściami szyfrującymi znak „b”. Jeśli chodzi o b1akkodmowę. Zmodyfikuje to w opisie wyzwania, aby wyjaśnić. Jeśli pierwszy znak jest zaszyfrowany, cyfra nie powinna być obecna.
Kevin Cruijssen,
1
Na przykład, gdy długość = 3, char = "a"; Postać "a??"ma 676 możliwych wyników, ale "1a?", "?a1", "2?a", "?2a", ma only104 wyników. Tak więc, jeśli próbuję wybrać jeden wynik z tych wszystkich 780 wyników, rozkład „pozycji zaszyfrowanej litery” wynosi 13: 1: 1, a nie 1: 1: 1. I uznałbym to za działanie „równomiernie losowe”.
tsh

Odpowiedzi:

3

Pyth, 22 bajty

smsXWJOQXmOGQJdO-UQJJz

Wypróbuj online.

Używa małych i zerowania.

Wyjaśnienie

Bardzo prosty algorytm.

                           Implicit: read word in z
                           Implicit: read number in Q
 m                   z     For each char d in z:
      OQ                     Choose a number 0..Q-1
     J                       and call it J.
         m  Q                Make an array of Q
          OG                 random letters.
        X     d              Place d in this string
             J               at position J.
    W                        If J is not 0,
   X                J        place J in this string
               O             at a random position from
                 UQ          0..Q-1
                -  J         except for J.
  s                          Concatenate the letters.
s                          Concatenate the results.
PurkkaKoodari
źródło
5

Perl 6 , 125 bajtów

->\n{*.&{S:g{.}=(65..90)>>.chr.roll(n).join.subst(/./,$/,:th($!=roll 1..n:)).subst(/./,$!,:th($!-1??(^n+1$!).roll!!n+1))}}

Wypróbuj online!

Pobiera dane wejściowe i wyjściowe dużymi literami. Wymaga curry wejściowego, jak f(n)(string). Używa 1 indeksowania.

Wyjaśnienie:

->\n{*.&{ ...  }}   # Anonymous code block that takes a number n and returns a function
     S:g{.}=        # That turns each character of the given string into
                          .roll(n)      # Randomly pick n times with replacement
            (65..90)>>.chr              # From the uppercase alphabet
                                  .join # And join
            .subst(                         ) # Then replace
                   /./,  ,:th($!=roll 1..n:)  # A random index (saving the number in $!)
                       $/               # With the original character
            .subst(                )    # Replace again
                   /./,$!,:th( ... )    # The xth character with $!, where x is:
                           $!-1??          # If $! is not 1
                                 (^n+1$!).roll       # A random index that isn't $!
                                               !!n+1  # Else an index out of range
Jo King
źródło
4

Python 2 , 187 177 176 156 154 148 bajtów

lambda l,s:''.join([chr(choice(R(65,91))),c,`n`][(j==n)-(j==i)*(n>0)]for c in s for n,i in[sample(R(l),2)]for j in R(l))
from random import*
R=range

Wypróbuj online!

Wykorzystuje wielkie litery i cyfry 0-indeksowane.

-3 bajty, dzięki Kevin Cruijssen

TFeld
źródło
@KevinCruijssen Thanks :)
TFeld
Co sample(R(l),2)[::1|-(random()<.5)]znaczy
l4m2
@ l4m2 Pobiera 2 liczby range(l)i przetasowuje je. Ale najwyraźniej próbka nie gwarantuje porządku, więc nie jest potrzebna :)
TFeld
Nie możesz usunąć nawiasu (j==i)*(n>0)? Mnożenie ma pierwszeństwo operatora przed odejmowaniem, prawda?
Kevin Cruijssen,
1
@KevinCruijssen Tak, zapomniałem je usunąć, gdy miałem pewne problemy
TFeld
3

JavaScript (Node.js) , 135 bajtów

n=>f=([c,...s])=>c?(g=n=>n?g(--n)+(n-p?n-q|!p?(r(26)+10).toString(36):p:c):'')(n,r=n=>Math.random()*n|0,p=r(n),q=r(n-1),q+=q>=p)+f(s):s

Wypróbuj online!

Dziękujemy Arnauldowi za 1B

l4m2
źródło
3

R , 134 132 123 bajtów

function(S,n,s=sample)for(k in utf8ToInt(S)){o=k+!1:n
P=s(n,1)
o[-P]=s(c(P[i<-P>1],s(17:42,n-1-i,T)))+48
cat(intToUtf8(o))}

Wypróbuj online!

Przyjmuje wielkie litery.

Objaśnienie starego kodu (głównie tego samego podejścia):

function(S,n){s=sample				# alias
K=el(strsplit(S,""))				# split to characters
o=1:n						# output array
for(k in K){					# for each character in the string
P=s(n,1)					# pick a Position for that character
o[-P]=						# assign to everywhere besides P:
      s(					# a permutation of:
	c(P[i<-P>1],				# P if it's greater than 1
		s(letters,n-1-i,T)))		# and a random sample, with replacement, of lowercase letters
o[P]=k						# set k to position P
cat(o,sep="")}}					# and print
Giuseppe
źródło
2

Java (JDK) , 193 bajty

s->n->s.flatMap(c->{int a[]=new int[n],i=n,x=0;for(;i-->0;)a[i]+=Math.random()*26+97;a[i+=Math.random()*n+1]=c;x+=Math.random()*~-n;if(i>0)a[x<i?x:x+1]=48+i;return java.util.Arrays.stream(a);})

Wypróbuj online!

  • Indeks jest oparty na 0.
  • Ten wpis używa IntStream(przeszedł String::chars) jako danych wejściowych, a także liczby i zwraca innyIntStream .
  • Przesyłanie z doubledo intjest niepotrzebne z powodu +=włamania.
Olivier Grégoire
źródło
2

Japt , 29 bajtów

;£=VöJ;CöV hUÎX hUÅÎUÎ?UÎs:Cö

Wypróbuj online!

Zero indeksowane.

Wyjaśnienie:

;                                :Set C = [a...z]
 £                               :For each character of the input:
  =VöJ;                          : Get two different random indexes from [0,length)
       CöV                       : Get 5 random letters
           hUÎX                  : Replace one at random with the character from the input
                hUÅÎ             : Replace a different random character with:
                    UÎ?          :  If the input character was not placed at 0:
                       UÎs       :   The index of the input character
                          :      :  Otherwise:
                           Cö    :   A random letter
                                 :Implicitly join back to a string
Kamil Drakari
źródło
2

C, 115 bajtów

g(_,n)char*_;{int i=rand(),j=i%~-n,k=0;for(i%=n;k<n;k++)putchar(k-i?!i|i<k^k-j?rand()%26+97:48+i:*_);*++_&&g(_,n);}

Wypróbuj online!

0-indeksowane, małe litery.

Nieznacznie pozbawiony golfa i rozwinięty:

g(char*_,int n) {
    int i = rand(), j = i%(n-1), k = 0;
    for(i = i%n; k<n; k++)
        putchar(k!=i ? i!=0 || k==j + (k>i)
                          ? rand()%26 + 'A'
                          : i + '0')
                    : *_);
    if (*++_!=0) g(_,n);
}

Kod powinien być dość prosty. Dwa losowe i, jwygenerowane w jednym rand()wywołaniu, są tak samo niezależne, ponieważ gcd ( n, ~-n) = 1 i RAND_MAXjest duże.

attinat
źródło
1
Witamy w PPCG! :)
Kudłaty
1

Czysty , 256 bajtów

import StdEnv
s::!Int->Int
s _=code {
ccall time "I:I"
ccall srand "I:I"
}
r::!Int->Int
r _=code {
ccall rand "I:I"
}
$n|s 0<1#k=map\e.r e rem n
=flatten o map\c.hd[map(\i|i==x=c=toChar if(i==y&&x>0)(x+48)(r i rem 26+97))[0..n-1]\\x<-k[0..]&y<-k[0..]|x<>y]

Wypróbuj online!

Wybiera:

  • losowy x(pozycja postaci w segmencie)
  • losowa, yktóra nie jest równa x(pozycja cyfry w segmencie)
  • losowa mała litera dla każdej pozycji, która nie jest równa xani różna, ychyba że xwynosi zero
Obrzydliwe
źródło
1

JavaScript, 134 bajty

l=>w=>w.replace(/./g,c=>eval("for(s=c;!s[l-1]||s[t?t-1||9:0]!=c;t=s.replace(/\\D/g,''))s=(p=Math.random()*36**l,p-p%1).toString(36)"))

Wypróbuj online!

W odpowiedzi wybrano jednolicie zakodowany ciąg ze wszystkich możliwych zakodowanych ciągów. Dlatego bardziej możliwe jest, aby zakodowana litera była pierwsza.

tsh
źródło
1

C # (interaktywny kompilator Visual C #) , 171 bajtów

s=>n=>{var r=new Random();return s.SelectMany(c=>{int i=r.Next(n),j=r.Next(n-1);j+=j<i?0:1;return new int[n].Select((_,k)=>(char)(i==k?c:j==k&i>0?i+49:r.Next(26)+97));});}

Wypróbuj online!

Wyjaśnienie...

// s is the input string
// n is the input length
s=>n=>{
  // we need to create an instance
  // of Random and use throughout
  var r=new Random();
  // iterate over s, each iteration
  // returns an array... flatten it
  return s.SelectMany(c=>{
    // i is the position of the letter
    // j is the position of the number
    int i=r.Next(n), j=r.Next(n-1);
    // ensure i and j are different
    j+=j<i?0:1;
    // create an iterable of size n
    return new int[n]
      // iterate over it with index k
      .Select((_,k)=>(char)(
        // return the letter
        i==k?c:
        // return the number
        j==k&i>0?i+49:
        // return a random letter
        r.Next(26)+97)
      );
  });
}
dana
źródło
1

Węgiel drzewny , 35 30 bajtów

NθFS«≔‽θη≔∧η‽Φθ⁻κηζFθ≡κζIηηι‽β

Wypróbuj online! Link jest do pełnej wersji kodu. 0-indeksowane. Wyjaśnienie:

Nθ

Wprowadź długość.

FS«

Wpisz słowo i zapętl znaki.

≔‽θη

Wybierz losową pozycję rozszyfrowanej litery.

≔∧η‽Φθ⁻κηζ

Wybierz inną losową pozycję cyfry, chyba że litera znajduje się w pozycji 0, w którym to przypadku umieść cyfrę również w pozycji 0.

Fθ≡κ

Zapętlić raz dla każdego znaku wyjściowego i włączyć pozycję.

ζIη

Jeśli jest to pozycja cyfry, wyślij pozycję rozszyfrowanej litery.

ηι

Ale jeśli jest to pozycja rozszyfrowanej litery, wyślij ją. Ma to pierwszeństwo przed pozycją cyfry, ponieważ węgiel zajmuje ostatni wpis, jeśli wiele skrzynek przełączników ma tę samą wartość.

‽β

W przeciwnym razie wypisz losową literę.

Neil
źródło
0

05AB1E , 26 bajtów

ε²Ý¨Ω©A.r²£Šǝ®Āi®²Ý¨®KΩǝ]J

0-indeksowane.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

ε            # Map over the characters of the first (implicit) input-string:
 ²Ý¨         #  Create a list in the range [0, second input)
    Ω        #  Get a random item from this list
     ©       #  Store it in the register (without popping)
 A           #  Push the lowercase alphabet
  .r         #  Shuffle it
    ²£       #  Leave only the first second input amount of characters
      Š      #  Triple swap, so the stack order becomes:
             #  random index; random string; map-character
       ǝ     #  Insert the map-character at this random index into the random string
 ®Āi         #  If the random index was NOT 0:
    ®        #   Push the random index
    ²Ý¨      #   Push the list in the range [0, second input) again
       ®K    #   Remove the random index from this list
         Ω   #   Get a random item from this list
          ǝ  #   Insert the first random index at the second random index into the string
]            # Close both the if-else and map
 J           # Join all strings together (and output implicitly)
Kevin Cruijssen
źródło