Szyfr parzysty / nieparzysty ASCII

13

Zdefiniujemy nieparzysty / parzysty szyfr ASCII za pomocą poniższego pseudokodu:

Define 'neighbor' as the characters adjacent to the current letter in the string

If the one of the neighbors is out of bounds of the string, treat it as \0 or null

Take an input string

For each letter in the string, do
  If the 0-based index of the current letter is even, then
    Use the binary-or of the ASCII codes of both its neighbors
  Else
    If the ASCII code of the current letter is odd, then
      Use the binary-or of itself plus the left neighbor
    Else
      Use the binary-or of itself plus the right neighbor
  In all cases,
    Convert the result back to ASCII and return it
  If this would result in a code point 127 or greater to be converted, then
    Instead return a space

Join the results of the For loop back into one string and output it

Na przykład dla danych wejściowych Hellodane wyjściowe są emmol, ponieważ

  • W Hzakręty na \0 | 'e'których jeste
  • eOkazuje się 'e' | 'l', albo 101 | 108, co jest 109lubm
  • Pierwszy lzmienia się również w 101 | 108lubm
  • Drugi lzamienia się w 108 | 111, czyli 111lubo
  • oOkazuje się 108 | \0, lubl

Wejście

  • Zdanie złożone wyłącznie z drukowalnych znaków ASCII, w dowolnym odpowiednim formacie .
  • W zdaniu mogą znajdować się kropki, spacje i inne znaki interpunkcyjne, ale zawsze będzie to tylko jedna linia.
  • Zdanie będzie miało co najmniej trzy znaki.

Wynik

  • Powstały szyfr, oparty na regułach opisanych powyżej, zwrócony jako ciąg lub wynik.

Zasady

  • Dopuszczalny jest pełny program lub funkcja.
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).

Przykłady

Dane wejściowe w jednym wierszu, dane wyjściowe w następującym. Puste linie oddzielają przykłady.

Hello
emmol

Hello, World!
emmol, ww~ved

PPCG
PSWG

Programming Puzzles and Code Golf
r wogsmmoonpuu ~ meannncoooeggonl

abcdefghijklmnopqrstuvwxyz
bcfefgnijknmno~qrsvuvw~yzz

!abcdefghijklmnopqrstuvwxyz
aaccgeggoikkomoo qsswuww yy

Test 123 with odd characters. R@*SKA0z8d862
euutu133www|todddchizsscguwssr`jS{SK{z~|v66
AdmBorkBork
źródło
3
Czy to naprawdę szyfr? Nie wydaje się to sposobem na jego rozszyfrowanie.
rura
Biorąc pod uwagę, że ozmiany lw pierwszym przykładzie, jestem prawie pewien, że twoje specyfikacje zapewniają, że pierwszy onie zmieni się lw drugim przykładzie. Powinien zmienić się na 'l' | ',', cokolwiek to jest, prawda?
Greg Martin
@pipe Tak. Niezupełnie „szyfr”, ale nie jestem pewien, jak to nazwać. To naprawdę nie jest skrót. Spośród tagów, które mamy, „szyfr” wydawał się najbliższy, więc po to poszedłem.
AdmBorkBork
@GregMartin Tak, chodzi o 'l' | ','to 108 | 44 --> 1101111 | 0101100, co się staje 108, co jest l. ,Dzieje się w kolejce z l, więc nie ma zmiany, gdy binarnie lub odbywa.
AdmBorkBork
Och, to naprawdę binarny-LUB ... Myślałem o binarnym-XOR. Dziękuję za wyjaśnienie. Z drugiej strony, mówi to jeszcze bardziej o spostrzeżeniu Fajki, że tego „szyfru” nie można tak naprawdę rozszyfrować, o ile wiem.
Greg Martin

Odpowiedzi:

1

Galaretka , 33 31 bajtów

2ịḂị|2\
|ṚḢ,Ç
O0,0jṡ3µÇ€⁸JḂ¤ị"Ọ

Proste podejście, które z pewnością można skrócić.

Wypróbuj online!

mile
źródło
4

Perl, 63 62 bajtów

Obejmuje +4 za -lp

Podaj dane na STDIN

oddeven.pl:

#!/usr/bin/perl -lp
s%.%(--$|?$n|$':$&|(ord$&&1?$n:$'))&($n=$&,~v0)%eg;y;\x7f-\xff; ;

Działa to tak, jak pokazano, ale aby uzyskać deklarowany wynik, należy go umieścić w pliku bez końcowej ;i nowej linii, a \xhhznaki zmiany znaczenia należy zastąpić ich literalnymi wartościami. Możesz to zrobić, umieszczając powyższy kod w pliku i uruchamiając:

perl -0pi -e 's/\\x(..)/chr hex $1/eg;s/;\n$//' oddeven.pl
Ton Hospel
źródło
3

Python 2, 138 131 bajtów

s="\0%s\0"%input();r=''
for i in range(len(s)-2):L,M,R=map(ord,s[i:i+3]);a=i%2and[R,L][M%2]|M or L|R;r+=chr(a*(a<127)or 32)
print r

Wypróbuj online (zawiera wszystkie przypadki testowe)

Mniej golfa:

def f(s):
    s="\0%s\0"%s
    r=''
    for i in range(1,len(s)-1):
        if i%2: # even (parity is changed by adding \x00 to the front)
            a=ord(s[i-1]) | ord(s[i+1])
        else:   # odd
            a=ord(s[i])
            if a%2: # odd
                a|=ord(s[i-1])
            else:   # even
                a|=ord(s[i+1])
        r+=chr(a if a<127 else 32)
    print r

Wypróbuj online (bez golfa)

Dodałem \x00po obu stronach łańcucha, aby nie musiałem się tym martwić podczas bitowego oringowania. Pętlę wzdłuż oryginalnych znaków ciągu, wykonując operacje bitowe i dodając je do wyniku, zgodnie z regułami parzystości.

mbomb007
źródło
Dang, jestem zazdrosny o to |=... odpowiednikiem w PowerShell byłby$a=$a-bor$b
AdmBorkBork
@ TimmyD Właściwie nie skończyłem go używać, ale tak. To miłe. Gdyby tylko Python a?b:clubił JS.
mbomb007
Możesz zastąpić, jeśli% 2: # nieparzyste a | = ord (s [i-1]) else: # parzyste | = ord (s [i + 1]) z | = ord (s [i + 1- 2 * (a% 2)])
NoSeatbelts 25.09.16
@NoSeatbelts To mój niepolecany kod, który pozostanie bez zmian do celów czytelności. Zgłoszenie w golfa jest najlepszym programem.
mbomb007,
2

C - 101 bajtów

i,k;f(char*p){for(i=0;*p;++p,++i)putchar((k=i&1?*p&1?*p|p[-1]:*p|p[1]:i?p[-1]|p[1]:p[1])<127?k:' ');}

Nie musimy nawet sprawdzać, czy jest to ostatni element w ciągu, ponieważ łańcuchy w C są zakończone zerem.

Wyjaśnienie

Raczej prosty:

Użyj & 1, aby sprawdzić, czy wyrażenia nieparzyste / parzyste oraz potrójne wyrażenia zastępują if / elses. Zwiększ wartość * p, aby zmniejszyć liczbę wymaganych nawiasów.

Brak pasów bezpieczeństwa
źródło
Dobra odpowiedź - witamy w PPCG!
AdmBorkBork,
2

Mathematica, 152 bajty

FromCharacterCode[BitOr@@Which[OddQ@Max@#2,#~Drop~{2},OddQ@#[[2]],Most@#,True,Rest@#]/._?(#>126&)->32&~MapIndexed~Partition[ToCharacterCode@#,3,1,2,0]]&

Wyjaśnienie

ToCharacterCode@#

Konwertuje ciąg znaków na kody ASCII

Partition[...,3,1,2,0]

Dzieli kody ASCII na długość 3, przesunięcie 1 partycji, z dopełnianymi zerami.

...~MapIndexed~...

Stosuje funkcję dla każdej partycji.

Which[...]

If...else if... elsew Mathematica .

OddQ@Max@#2

Sprawdza, czy indeks (# 2) jest nieparzysty. ( Maxsłuży do spłaszczania); ponieważ indeks Mathematica zaczyna się od 1, użyłem OddQtutaj, nieEvenQ

Drop[#,{2}]

Pobiera kody ASCII lewego i prawego sąsiada.

OddQ@#[[2]]

Sprawdza, czy kod ASCII odpowiedniego znaku jest nieparzysty.

Most@#

Pobiera kody ASCII znaku i lewego sąsiada.

Rest@#

Pobiera kody ASCII znaku i prawego sąsiada.

BitOr

Stosuje lub działa.

/._?(#>126&)->32

Zamienia wszystkie liczby większe niż 126 na 32 (spacja).

FromCharacterCode

Konwertuje kod ASCII z powrotem na znaki i dołącza do nich.

JungHwan Min
źródło
Witamy w PPCG! Czy możesz dodać jakieś wyjaśnienie dla osób (takich jak ja), które nie są dobrze zaznajomione z matematyką? Koniecznie sprawdź też Porady dotyczące gry w golfa w Mathematica, aby uzyskać sugestie. Miłego pobytu!
AdmBorkBork,
1
Kilka ulepszeń: Akceptowanie i zwracanie listy znaków zamiast rzeczywistego obiektu łańcuchowego jest całkowicie w porządku i znacznie oszczędza na tych From/ToCharacterCodefunkcjach. Wtedy to wygląda jak Droppuszki użycie notacji Infix: #~Drop~{2}. I wygląda na to, że aplikujesz BitOrna każdy możliwy wynik, Whichwięc dlaczego nie zastosować go później i tylko raz?
Martin Ender
2

Ruby 133 128 108 106 bajtów

Jordan pomógł mi zaoszczędzić 20 bajtów, a cia_rana pomógł mi zaoszczędzić 2 bajty :)

->s{p s[-i=-1]+s.bytes.each_cons(3).map{|x,y,z|i+=1;a=i%2>0?x|z :y%2>0?y|x :y|z;a>126?' ':a.chr}*""+s[-2]}

s jest brany jako ciąg wejściowy.

Przykładowe dane wyjściowe z s="Test 123 with odd characters. R@*SKA0z8d862":

"euutu133www|todddchizsscguwssr`jS{SK{z~|v66"

Wyjaśnienie

Powyższy kod jest bardzo nieczytelny, więc oto wyjaśnienie. Kod jest trochę hacky, jestem całkiem nowy w Ruby, więc założę się, że jest to krótszy sposób :)

b=s[1] # for the first character we always use the right neighbour
       # because `\0 | x` will always return x any way. 0 is the
       # left neighbour and x is the right neigbour
s.bytes.each_cons(3).with_index{|c,i| # oh boy, first we convert the string to ascii with each_byte
                                          # we then traverse the resulting array with three elements at
                                          # a time (so for example if s equals "Hello", c will be equal
                                          # to [72, 101, 108])
  if (i+1) % 2 < 1 # if the middle letter (which is considered our current letter) is even
    a = c[0] | c[2] # we use the result of binary-or of its neighbours
  else
    if c[1] % 2 > 0 # if the code of the current letter is odd
      a = c[1] | c[0] # we use the result of binary-or of itself and its left neighbour
    else
      a = c[1] | c[2] # we use the result of binary-or of itself and its right neighbour
    end
  end
  if a>126
    b<<' ' # if the result we use is greater or equal to 127 we use a space
  else
    b<<a.chr # convert the a ascii value back to a character
  end
}
p b+s[-2] # same as the first comment but now we know that x | \0 will always be x
          # this time x is the last characters left neighbour
Linus
źródło
Jestem całkiem pewien, że dane wyjściowe muszą być w jednym wierszu, ponieważ dane wejściowe również.
mbomb007,
@ mbomb007 bummer, a następnie muszę użyć printzamiast p: p
Linus
@ TimmyD oh, więc nie mogę wydrukować go na wydruku w różnych momentach?
Linus
@ TimmyD ok, więc powyższe jest dozwolone? Teraz drukuje wszystko w jednym wierszu.
Linus
1
Możesz pisać jak pokazano poniżej:->s{p s[-i=-1]+s.bytes.each_cons(3).map{|x,y,z|i+=1;a=i%2>0?x|z :y%2>0?y|x :y|z;a>126?' ':a.chr}*""+s[-2]}
cia_rana
1

J, 42 bajty

4:u:3({.OR{:)`((2|1&{){2:OR/\|.)\0,~0,3&u:

Wykorzystuje właściwość, że czasowniki w J mogą być stosowane naprzemiennie przy użyciu gerunda `dla niektórych przysłówków, takich jak infix \.

Stosowanie

   f =: 4:u:3({.OR{:)`((2|1&{){2:OR/\|.)\0,~0,3&u:
   f 'Hello'
emmol
   f 'Hello, World!'
emmol,ww~ved
   f 'PPCG'
PSWG
   f 'Programming Puzzles and Code Golf'
rwogsmmoonpuu~meannncoooeggonl
   f 'abcdefghijklmnopqrstuvwxyz'
bcfefgnijknmno~qrsvuvw~yzz
   f '!abcdefghijklmnopqrstuvwxyz'
aaccgeggoikkomooqsswuwwyy
   f 'Test 123 with odd characters. R@*SKA0z8d862'
euutu133www|todddchizsscguwssr`jS{SK{z~|v66

Wyjaśnienie

4:u:3({.OR{:)`((2|1&{){2:OR/\|.)\0,~0,3&u:  Input: string S
                                      3&u:  Convert each char to an ordinal
                                    0,      Prepend 0
                                 0,~        Append 0
    3                           \           For each slice of size 3
     (      )`                                For the first slice (even-index)
          {:                                    Get the tail
      {.                                        Get the head
        OR                                      Bitwise OR the head and tail
             `(                )              For the second slice (odd-index)
                             |.                 Reverse the slice
                       2:   \                   For each pair
                         OR/                      Reduce using bitwise OR
                  1&{                           Get the middle value of the slice
                2|                              Take it modulo 2
                      {                         Index into the bitwise OR pairs and select
                                              Repeat cyclically for the remaining slices
4:u:                                        Convert each ordinal back to a char and return
mile
źródło
1

JavaScript (ES6), 125 118 114 bajtów

Żenująco długa, ale charCodeAti String.fromCharCodesam jest 29 bajtów. : - /

s=>[...s].map((_,i)=>String.fromCharCode((x=(C=i=>s.charCodeAt(i))((i-1)|1)|C(i+1-2*(C(i)&i&1)))>126?32:x)).join``

Jak to działa

Każdy znak na pozycji ijest tłumaczony następującą formułą, która obejmuje wszystkie zasady jednocześnie:

C((i - 1) | 1) | C(i + 1 - 2 * (C(i) & i & 1))

gdzie C(n)zwraca kod ASCII n-tego znaku ciągu wejściowego.

Próbny

let f =
    
s=>[...s].map((_,i)=>String.fromCharCode((x=(C=i=>s.charCodeAt(i))((i-1)|1)|C(i+1-2*(C(i)&i&1)))>126?32:x)).join``

console.log(f("Hello"));
console.log(f("Hello, World!"));
console.log(f("PPCG"));
console.log(f("Programming Puzzles and Code Golf"));
console.log(f("abcdefghijklmnopqrstuvwxyz"));
console.log(f("!abcdefghijklmnopqrstuvwxyz"));
console.log(f("Test 123 with odd characters. R@*SKA0z8d862"));

Arnauld
źródło
1

PHP, 107 97 bajtów

prawdopodobnie gra w golfa.

for(;$i<strlen($s=$argv[1]);$i++)echo chr(ord($s[$i-1+$i%2])|ord($s[$i+1-2*($i&ord($s[$i])&1)]));
Tytus
źródło
1

C #, 145 bajtów

s=>{var r=s[1]+"";int i=1,l=s.Length,c;for(;i<l;i++){c=i>l-2?0:s[i+1];c=i%2<1?s[i-1]|c:s[i]|(s[i]%2>0?s[i-1]:c);r+=c>'~'?' ':(char)c;}return r;};

Pełny program z nieprzylepioną metodą i przypadkami testowymi:

using System;

namespace ASCIIOddEvenCipher
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<string,string>f= s=>
            {
                var r = s[1] + "";
                int i = 1, l = s.Length, c;
                for(;i < l; i++)
                {
                    c = i>l-2 ? 0 : s[i+1];
                    c = i%2<1 ? s[i-1]|c : s[i]|(s[i]%2>0 ? s[i-1] : c);
                    r += c > '~' ? ' ' : (char)c;
                }
                return r;
            };

            //test cases:
            Console.WriteLine(f("Hello"));  //emmol
            Console.WriteLine(f("Hello, World!"));  //emmol, ww~ved
            Console.WriteLine(f("PPCG"));   //PSWG
            Console.WriteLine(f("Programming Puzzles and Code Golf"));  //r wogsmmoonpuu ~ meannncoooeggonl
            Console.WriteLine(f("abcdefghijklmnopqrstuvwxyz")); //bcfefgnijknmno~qrsvuvw~yzz
            Console.WriteLine(f("!abcdefghijklmnopqrstuvwxyz"));    //aaccgeggoikkomoo qsswuww yy
            Console.WriteLine(f("Test 123 with odd characters. R@*SKA0z8d862"));    //euutu133www|todddchizsscguwssr`jS{SK{z~|v66
        }
    }
}

To okazało się dłuższe niż myślałem ...

adrianmp
źródło