ASCII Нечетный / Четный Шифр

13

Мы определим нечетный / четный шифр ASCII через следующий псевдокод:

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

Например, для ввода Hello, вывод emmol, так как

  • В Hочереди к \0 | 'e'которой являетсяe
  • eПоворачивается 'e' | 'l', или 101 | 108, что 109илиm
  • Первый lтакже превращается в 101 | 108илиm
  • Второй lпревращается в 108 | 111, который является 111илиo
  • oПоворачивается 108 | \0, илиl

вход

  • Предложение, состоящее исключительно из печатных символов ASCII, в любом подходящем формате .
  • В предложении могут быть точки, пробелы и другие знаки пунктуации, но всегда будет только одна строка.
  • Предложение будет содержать не менее трех символов.

Выход

  • Полученный шифр, основанный на правилах, описанных выше, возвращается как строка или вывод.

Правила

  • Либо полная программа или функция приемлемы.
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

Примеры

Ввод в одну строку, вывод в следующую. Пустые строки отдельные примеры.

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
источник
3
Это действительно шифр? Кажется, не способ расшифровать это.
труба
Учитывая, что oизменения lв первом примере, я уверен, что ваши спецификации гарантируют, что первый oне изменится lво втором примере. Это должно измениться 'l' | ',', что бы это ни было, верно?
Грег Мартин
@pipe Да. Не совсем «шифр», но не совсем уверен, как это назвать. Это не совсем хеш, либо. Из тегов, которые у нас есть, «шифр» казался самым близким, поэтому я и пошел с этим.
AdmBorkBork
@GregMartin Да, это идет 'l' | ',', который есть 108 | 44 --> 1101111 | 0101100, который становится 108, который есть l. ,Происходит выстраиваться с l, так что нет никаких изменений при двоичном или происходит.
AdmBorkBork
О, это действительно двоичное ИЛИ ... Я думал о двоичном XOR. Спасибо за разъяснение. С другой стороны, это еще больше говорит о том, что Труба, насколько я могу судить, не может расшифровать этот «шифр».
Грег Мартин

Ответы:

4

Perl, 63 62 байта

Включает +4 для -lp

Внести вклад в STDIN

oddeven.pl:

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

Это работает, как показано, но для получения заявленной оценки это должно быть помещено в файл без финальной ;и новой строки, а escape- \xhhкоды должны быть заменены их литеральными значениями. Вы можете сделать это, поместив приведенный выше код в файл и запустив:

perl -0pi -e 's/\\x(..)/chr hex $1/eg;s/;\n$//' oddeven.pl
Тон Хоспел
источник
3

Python 2, 138 131 байт

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

Попробуйте онлайн (содержит все контрольные примеры)

Меньше гольфа:

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

Попробуйте онлайн (без игры в гольф)

Я добавляю \x00к обеим сторонам строки, чтобы мне не приходилось беспокоиться об этом во время битовой обработки. Я зацикливаюсь на исходных символах строки, выполняя побитовые операции и добавляя их к результату, следуя правилам проверки на четность.

mbomb007
источник
Черт, я завидую этому |=... эквивалент в PowerShell был бы$a=$a-bor$b
AdmBorkBork
@TimmyD На самом деле я не стал его использовать, но да. Мило. Если бы только Python был a?b:cкак JS.
mbomb007
Вы можете заменить, если a% 2: # odd a | = ord (s [i-1]) иначе: # даже a | = ord (s [i + 1]) на | = ord (s [i + 1- 2 * (a% 2)])
Ремни NoSeatbet
@NoSeatbelts Это мой код без кода, который будет оставлен как есть для удобства чтения. Представление в гольфе - лучшая программа.
mbomb007
2

C - 101 байт

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:' ');}

Нам даже не нужно проверять, является ли это последним элементом в строке, потому что строки в C заканчиваются нулем.

объяснение

Скорее просто:

Используйте & 1 для проверки нечетности / четности и троичных выражений для замены if / elses. Увеличьте char * p, чтобы уменьшить количество требуемых скобок.

NoSeatbelts
источник
Хороший ответ - добро пожаловать в PPCG!
AdmBorkBork
2

Mathematica, 152 байта

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

объяснение

ToCharacterCode@#

Преобразует строку в коды ASCII

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

Разбивает коды ASCII на длину 3, смещает 1, с дополнением 0.

...~MapIndexed~...

Применяет функцию для каждого раздела.

Which[...]

If...else if... elseв Mathematica .

OddQ@Max@#2

Проверяет, является ли индекс (# 2) нечетным. ( Maxдля выравнивания); так как индекс Mathematica начинается с 1, я использовал OddQздесь, а неEvenQ

Drop[#,{2}]

Принимает коды ASCII левого и правого соседей.

OddQ@#[[2]]

Проверяет, является ли код ASCII соответствующего символа нечетным.

Most@#

Принимает ASCII коды персонажа и левого соседа.

Rest@#

Принимает ASCII коды персонажа и правого соседа.

BitOr

Применяется или-операция.

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

Заменяет все числа больше 126 на 32 (пробел).

FromCharacterCode

Преобразует ASCII-код обратно в символы и соединяет их.

Юнг Хван Мин
источник
Добро пожаловать в PPCG! Не могли бы вы добавить немного объяснения людям (таким как я), которые не очень хорошо разбираются в Mathematica? Также не забудьте проверить советы по игре в гольф в Mathematica для некоторых предложений. Приятного пребывания!
AdmBorkBork
1
Несколько улучшений: Принятие и возврат списка символов вместо действительного строкового объекта вполне подходит и значительно экономит на этих From/ToCharacterCodeфункциях. Тогда это выглядит как ваша Dropмогут использовать инфиксную запись: #~Drop~{2}. И кажется, что вы применяете BitOrк каждому возможному выводу, Whichтак почему бы не применить его потом и только один раз?
Мартин Эндер
2

Рубин 133 128 108 106 байт

Джордан помог мне сэкономить 20 байтов, а cia_rana помог мне сэкономить 2 байта :)

->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 берется в качестве входной строки.

Пример вывода с s="Test 123 with odd characters. R@*SKA0z8d862":

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

объяснение

Приведенный выше код очень нечитабелен, поэтому здесь есть объяснение. Код хакерский, я не знаком с ruby, так что держу пари, что есть более короткий способ сделать это :)

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
Линус
источник
Я вполне уверен, что вывод должен быть в одной строке, так как ввод тоже.
mbomb007
@ mbomb007 Облом, тогда я должен использовать printвместо p: р
Линус
@TimmyD о, так что я не могу распечатать его на выходе в разное время?
Линус
@TimmyD хорошо, так что выше разрешено? Теперь он печатает все в одну строку.
Линус
1
Вы можете написать, как показано ниже:->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 байта

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

Использует свойство, которое глаголы в J могут применяться поочередно, используя герунду `для определенных наречий, таких как инфикс \.

использование

   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

объяснение

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
миль
источник
1

JavaScript (ES6), 125 118 114 байт

Неловко долго, но charCodeAtи в String.fromCharCodeодиночку стоят 29 байтов. : - /

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``

Как это устроено

Каждый символ в позиции iпереводится по следующей формуле, которая охватывает все правила сразу:

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

где C(n)возвращает ASCII-код n-го символа входной строки.

демонстрация

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
источник
1

PHP, 107 97 байт

возможно гольф

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)]));
Titus
источник
1

C #, 145 байт

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

Полная программа с методикой ungolfed и тестовыми примерами:

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

Это оказалось дольше, чем я думал ...

adrianmp
источник