Cifra incremental


19

Essa tarefa é bastante simples e utiliza três caracteres "operadores" distintos. Sua tarefa é, dada uma simples seqüência de letras, executar a seguinte tarefa para codificá-lo usando <, >, *. Você pode optar por usar letras maiúsculas ou minúsculas, não precisa lidar com as duas.


Explicação de cifra

A cifra é simples, você está usando operações de incremento e decremento para passar da letra 1 até a letra final, *sendo sua função "enviar". O operador para "incremento" será >e "decremento" será <.

Um exemplo usando a palavra adbc:

  • Comece com a primeira letra da palavra, imprima essa letra. a
  • Em seguida, use >e <(como brainfuck) para "navegar" a letra atual para a próxima. a>resultaria em 'aumento' ade 1 para a letra b. a<resultaria em zque você está abaixando a letra (ela envolve, você sempre deve escolher a direção que resulta no menor número de operações).
  • Depois de produzir a combinação minimalizada correta de <e >produzir a *para indicar que chegamos à próxima letra.

As etapas para codificar adbcseriam:

a          # a
a>>>*      # ad
a>>>*<<*   # adb
a>>>*<<*>* # adbc

Exemplos

As etapas para codificar azaseriam:

a       # a
a<*     # az
a<*>*   # aza

Mais exemplos:

"abcdef"    =  "a>*>*>*>*>*"
"zyaf"      =  "z<*>>*>>>>>*"
"zzzzzz"    =  "z*****"
"z"         =  "z"
"zm"        =  "z<<<<<<<<<<<<<*" or "z>>>>>>>>>>>>>*" (equidistant)
"zl"        =  "z>>>>>>>>>>>>*"
"alphabet"  =  "a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*"
"banana"    =  "b<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*" OR "b<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*"
"abcdefghijklmnopqrstuvwxyz" = "a>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*"
"abcdefz"   =  "a>*>*>*>*>*<<<<<<*"

Regras

  • Estamos codificando, não decodificando, então não estrague tudo.
  • Você pode assumir que a mensagem conterá letras [A-Z]ou [a-z]sua escolha.
  • Você pode usar qualquer caractere que não seja da letra / numérico / reservado para indicar *(EG $).
  • Você deve ter o final *, não está implícito nas repetições.
  • Você pode assumir que não há cadeias vazias, mas um único caractere é possível.
  • Se for equidistante para a próxima letra, você poderá escolher uma direção.
  • Isso é , vitórias mais baixas na contagem de bytes.

Por favor, explique sua resposta, pois ajuda outras pessoas a aprender dessa maneira.


Só para esclarecer, o último caso de teste representa abcdefghijklmnopqrstuvwxyze não é sua própria entrada?
Nick Clifford

11
@NickClifford yes.
Magic Octopus Urn

Eu acho que zldeveria usar >.
Xnor

4
Você poderia verificar os exemplos? alphabeté na minha opinião a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*e zldeve ser z>>>>>>>>>>>>*e para bananadeveria existe uma segunda soluçãob<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*
Jörg Hülsermann

@ xnor correto, foi um erro de digitação manual de zm. A @jorg boas capturas, corrigida todas elas, foi um esforço manual.
Octopus Magic Urn

Respostas:


2

Geléia , 17 bytes

OIżN$ẋ"@€⁾><;€⁶ṭḢ

Usa um caractere de espaço no lugar de *(um espaço , ou uma nova linha , salva um byte ”*).

Funciona com qualquer maiúscula somente ou entrada somente minúsculas.

Experimente online! ou consulte uma suíte de testes (onde esses espaços são substituídos posteriormente*para facilitar a leitura).

Quão?

OIżN$ẋ"@€⁾><;€⁶ṭḢ - Main link: string s          e.g. "adbc"
O                 - cast s to ordinals                [97,100,98,99]
 I                - incremental differences           [3,-2,1]
    $             - last two links as a monad:
   N              -     negate                        [-3,2,-1]
  ż               -     zip together                  [[3,-3],[-2,2],[1,-1]]
         ⁾><      - literal ['>','<']                 "><"
      "@€         - using reversed @arguments for €ach zip with("):
     ẋ            -     repeat (-n are like zeros)    [[">>>",""],["","<<"],[">",""]]
            ;€    - concatenate €ach with:
              ⁶   -     literal ' '                   [[">>>","",' '],["","<<",' '],[">","",' ']]
               ṭ  - tack to:
                Ḣ -     head of s (1st char)          [['a'],[">>>","",' '],["","<<",' '],[">","",' ']]
                  - implicit print   (" not printed:) "a>>> << > "

11

Código de máquina 8086, 70 68 67 bytes

00000000  be 82 00 bf 43 01 57 31  d2 ac 3c 0d 74 2c 89 d1  |....C.W1..<.t,..|
00000010  88 c2 aa e3 f4 4f 28 c1  9f 88 e7 79 02 f6 d9 83  |.....O(....y....|
00000020  f9 0d 9f 76 05 83 e9 1a  f6 d9 30 fc 9e b0 3c 78  |...v......0...<x|
00000030  02 b0 3e f3 aa b0 2a aa  eb cf c6 05 24 b4 09 5a  |..>...*.....$..Z|
00000040  cd 21 c3                                          |.!.|
00000043

Como funciona:

            |   org 0x100
            |   use16
be 82 00    |       mov si, 0x82        ; source = command line arguments
bf 43 01    |       mov di, result      ; destination = result
57          |       push di
31 d2       |       xor dx, dx          ; clear dx
ac          |   n:  lodsb               ; al = *si++
3c 0d       |       cmp al, 0x0d        ; end of input reached? (newline)
74 2c       |       je q                ; jump to exit in that case
89 d1       |   @@: mov cx, dx          ; store last char in cl
88 c2       |       mov dl, al          ; and store the current char in dl
aa          |       stosb               ; *di++ = al
e3 f4       |       jcxz n              ; skip encoding this char if cx == 0 (only happens for the first char)
4f          |       dec di              ; move di pointer back
28 c1       |       sub cl, al          ; take the difference between this char and the last one
9f          |       lahf                ; store flags from last subtraction in bh
88 e7       |       mov bh, ah
79 02       |       jns @f
f6 d9       |       neg cl              ; make sure cl is positive
83 f9 0d    |   @@: cmp cl, 13          ; which way is shorter?
9f          |       lahf                ; also store these flags
76 05       |       jbe @f
83 e9 1a    |       sub cl, 26          ; invert cl if we're going backwards
f6 d9       |       neg cl
30 fc       |   @@: xor ah, bh          ; xor saved flags together
9e          |       sahf                ; load flags register with the result
b0 3c       |       mov al, '<'
78 02       |       js @f               ; now the sign flag tells us which operator to use
b0 3e       |       mov al, '>'
f3 aa       |   @@: rep stosb           ; while (cx--) *di++ = al
b0 2a       |       mov al, '*'         ; mark the end with an asterisk
aa          |       stosb
eb cf       |       jmp n               ; repeat
c6 05 24    |   q:  mov byte [di], '$'  ; mark end of string
b4 09       |       mov ah, 0x09        ; dos function: print string
5a          |       pop dx              ; dx = string pointer
cd 21       |       int 0x21            ; syscall
c3          |       ret
            |   result rb 0

Este. Isso está além do legal. Você fez isso REALMENTE rapidamente também, caramba.
Urna de polvo mágico

Obrigado. É praticamente a solução trivial. Só acontece de ser bastante curto em 8086.
user5434231

10

Python 3 , 87 bytes

r,*s=input();p=r
for c in s:d=(ord(p)-ord(c)-13)%26-13;r+='<'*d+'>'*-d+'*';p=c
print(r)

Experimente online!

Funciona com letras minúsculas ou maiúsculas.

O programa cria a sequência de saída rconforme itera sobre os caracteres na sequência de entrada. Ele armazena o caractere anterior como pe calcula a operação de incremento para passar ppara o novo caractere c.

O intervalo entre os caracteres é ord(c)-ord(p)e (ord(c)-ord(p)-13)%26-13leva o módulo 26 para o intervalo [-13..12]. Um resultado negativo significa que é mais curto renunciar e um resultado positivo significa intensificar. Isso precisa ser convertido em uma sequência de caracteres >ou <dependendo do sinal. Em vez de usar absou uma condição, aproveitamos a multiplicação de strings do Python, s*nfornecendo a string vazia quando nnegativa. Na expressão '<'*-d+'>'*d, a parte assinada incorretamente não contribui.

O estado inicial é tratado dividindo a entrada em seu primeiro caractere e o restante com a descompactação do Python 3 r,*s=input(). O caractere inicial é usado para começar a criar a string, bem como o caractere "anterior" inicial.

Obrigado a ovs por sugerir a mudança para o Python 3 para descompactar.



3

JavaScript (ES6), 118 109 107 bytes

A sequência de entrada não diferencia maiúsculas de minúsculas.

s=>s.replace(/./g,(c,i)=>(d=~~s-(s=parseInt(c,36)),i)?'<><>'[k=d/13+2|0].repeat([d+26,-d,d,26-d][k])+'*':c)

Como funciona

Ao contrário do Python, o operador do módulo JS retorna um número com o mesmo sinal que o dividendo, em vez do divisor. Além disso, o repeat()método JS gera um erro quando recebe um número negativo, em vez de retornar uma sequência vazia (e é significativamente mais longa do que uma simples *).

Esses são comportamentos bastante desfavoráveis ​​para esse desafio. Portanto, é melhor identificarmos em que caso exato estamos, em vez de confiar nos truques de matemática. (O que não significa que esses truques não existam, mas que eu não os encontrei.)

Abaixo está uma tabela que descreve os 4 casos possíveis, onde destá a distância assinada entre o caractere atual e o anterior:

d           | floor(d / 13) + 2 | direction | repeat
------------+-------------------+-----------+-------
-25 ... -14 |         0         |     <     | d + 26
-13 ... -1  |         1         |     >     | -d  
 +0 ... +12 |         2         |     <     | +d  
+13 ... +25 |         3         |     >     | 26 - d

Casos de teste


2

PHP, 127 bytes

for($l=ord($r=($s=$argn)[0]);$x=ord($s[++$i]);$l=$x)$r.=str_pad("",($a=abs($n=$l-$x))<14?$a:26-$a,"><"[$n>0^$a>13])."*";echo$r;

Casos de teste

PHP, 137 bytes

for($l=$r=($s=$argn)[0];$s[++$i];$l=$s[$i])$r.=str_pad("",$d=min($a=abs(ord($l)-ord($s[$i])),$b=26-$a),"><"[$d<$b^$l<$s[$i]])."*";echo$r;

Casos de teste


2

JavaScript (ES6), 111 103 bytes

f=
s=>s.replace(/./g,(c,i)=>(p=(n+26-(n=parseInt(c,36)))%26,i?'<>'[p+3>>4].repeat(p>13?26-p:p)+'*':c),n=0)
<input oninput=o.textContent=f(this.value)><pre id=o>

s=>[...s].map(c=>(n=parseInt(c,36),p&&(p=(n+26-p)%26,s+='><'[p+3>>4].repeat(p>13?26-p:p)+'*'),p=n),s=s[p=0])&&s

Originalmente versão que teve 111 bytes antes de eu adaptado @ truque de configuração de Arnauld nenquanto computação p, eu acho que provavelmente há um outro truque usando sem vez de nmas está ficando tarde, então eu não vou incomodar .:


2

Haskell (lambdabot), 161 153 bytes

w(s:n)=s:(join.snd$mapAccumL(ap(,).g)s n);g c n|q<-[c..'z']++['a'..c],(Just l,s)<-minimum$first(elemIndex n)<$>[(q,'>'),(reverse q,'<')]=(s<$[1..l])++"*"

Experimente online!


Explicação:

-- Encode a single letter
g c n | q          <- [c..'z']++['a'..c]        -- The alphabet starting from letter c, looping around
      , (Just l,s) <- minimum                   -- Choose the smallest of ..
                    $ first(elemIndex n)        -- the index of the letter n ..
                  <$> [(q,'>'),(reverse q,'<')] -- from the alphabet q and its reverse

      = (s<$[1..l]) -- Repeat < or > the same number of times as the index of n ..
     ++ "*"         -- and append *

-- Encode the whole string
w (s:n) = s                                -- Yield the first char of the input
        : ( join . snd                     -- Concatinate the result of ..
          $ mapAccumL (\a b->(b,g a b))s n -- executing the g function on each letter of the input string ..
                                           -- except the first, passing the previous letter as the 'c' ..
                                           -- argument on each iteration
          )

2

EXCEL VBA 130 bytes

s="":p=Mid(s,1,1):For i=1 To Len(s)-1:b=Asc(Mid(s,i+1,1)):a=Asc(Mid(s,i,1)):p=p &String(abs(b-a),IIf(b>a,">","<"))&"*":Next:[a1]=p

Execute-o na janela Imediata do Excel VBA.

Explicação:

Simples para loop que, com a função String, repita o número de vezes ">" ou "<" n em que n é a diferença ascii entre a cadeia de caracteres ie1 + 1.


2

Java 7-, 232 bytes

class C{static void main(String[]a)throws Exception{int i=System.in.read(),j,d,c;p(i);while((j=System.in.read())>10){d=(j-i+26)%26;c=d>13?-1:1;while(d%26>0){d-=c;p(61+c);}p(42);i=j;}}static void p(int k){System.out.print((char)k);}}

Praticamente a solução trivial. Ungolfed e comentou:

class C {
    static void main(String[] a) throws Exception {
        int i = System.in.read(), j, d, c; // i is the last character. j is the current character. d is the difference. c is the direction (-1 is left, 1 is right)
        p(i); // print the starting character first
        while ((j = System.in.read()) > 10) { // keep going until a newline is hit (or an EOF/EOL for -1)
            d = (j - i + 26) % 26; // get the difference (always positive) by wrapping around
            c = d > 13 ? -1 : 1; // get the direction by finding which way is shorter, going right when it's a tie
            while (d % 26 > 0) { // keep going until the current character is reached
                d -= c; // reduce d in the right direction
                p(61 + c); // < is 60 = 61 + (-1), > is 62 = 61 - (-1)
            }
            p(42); // print an asterisk
            i = j; // set the current character to the new reference point
        }
    }

    static void p(int k) {
        System.out.print((char) k);
    }
}

2

C, 170 bytes

e(c){putchar(c);}i;m(a,b){i=b-a?a>b?b-a<14?b-a:-(a+26-b):a-b<14?-(a-b):b+26-a:0;while(i>0)e(62),i--;while(i<0)e(60),i++;}f(char*l){e(*l);while(l[1])m(*l,l[1]),e(42),l++;}

Live detalhado

e(c){ putchar(c); } // encode

g(a,b) // obtain required transition
{
    return (b-a) // calculate distance

         ? (a > b // distance is non-zero

             // if b comes after a
             ? (b-a < 14 // if forward is a shorter path
                 ? b-a // go forward
                 : -(a+26-b)) // otherwise go backward

             // if b comes before a
             : (a-b < 14 // if backward is a shorter path
                 ? -(a-b) // go backward
                 : b+26-a)) // otherwise go forward

         : 0; // if distance is 0
}

// transition
i;m(a,b)
{
    // obtain required transition
    i=g(a,b);

    // encode forward transition
    while(i>0)e('>'), i--;

    // encode backward transition
    while(i<0)e('<'),i++;
}

// incremental cipher function
f(char*l)
{
    e(*l); // encode first character

    while(*(l+1)) // while next character is not END-OF-STRING
        m(*l,*(l+1)), // do transition from current to next character
        e('*'), // encode
        l++; // next
}

Solução legal. Provavelmente é mais fácil entender o seguinte, mas com um byte a mais:#define x q<14?q:q+26 e(c){putchar(c);}i,q;m(a,b){q=b-a;i=q?(a>b?x:-x):0;while(i>0)e('>'),i--;while(i<0)e('<'),i++;}f(char*l){e(*l);while(*(l+1))m(*l,*(l+1)),e('*'),l++;}
Moreaki 19/04/19

11
@ Moreaki Thx, mas este é um código de golfe, por isso sempre buscamos reduzir a contagem de bytes, de qualquer maneira eu adicionei explicações detalhadas sobre como meu código funciona.
precisa saber é o seguinte

2

JavaScript (ES6), 140 128 129 111 113 bytes

Eu segui uma rota diferente para as outras soluções JS, mas não funcionou muito bem - eis o que tenho até agora:

f=

([x,...s])=>x+s.map(y=>`<><>`[r=(d=y[c=`charCodeAt`]()-x[c](x=y))/13+2|0].repeat([d+26,-d,d,26-d][r])+`*`).join``

i.addEventListener("input",()=>o.innerText=i.value&&f(i.value))
console.log(f("adbc"))
console.log(f("aza"))
console.log(f("abcdef"))
console.log(f("zyaf"))
console.log(f("zzzzzz"))
console.log(f("z"))
console.log(f("zm"))
console.log(f("zl"))
console.log(f("alphabet"))
console.log(f("banana"))
console.log(f("abcdefghijklmnopqrstuvwxyz"))
console.log(f("abcdefz"))
<input id=i>
<pre id=o>

  • Economizou 12 bytes graças a uma sugestão de Luke sobre a destruição da string.
  • Adicionado 1 byte, corrigindo uma leitura incorreta do desafio, o que achei que permitia um caractere de impressão final implícito.
  • Economizou outros 18 bytes graças a uma extensa reescrita de Luke.
  • Adicionados 2 bytes, pois parece que os números não são caracteres de impressão válidos.

Original, 131 bytes


11
([x,...s])=>x+s.map(...)salva 12 bytes. Observe que você também deve anexar um caractere de impressão ao final. Sugiro usar um número, que custará apenas 2 bytes em `1`+1vez de `*`.
Luke

Obrigado Luke; Eu tinha esquecido que poderia desestruturar uma entrada de string assim. Eu devo ter interpretado mal o desafio ontem à noite; Eu poderia jurar que o último caractere impresso estava implícito. Infelizmente, simplesmente colocá-lo após o joinresultado resultaria em uma saída inválida para entradas de letra única. No entanto, mover o caractere de impressão dentro do mapmétodo custa apenas 1 byte.
Shaggy

11
([x,...s])=>x+s.map(y=>'<><>'[r=(d=y[c='charCodeAt']()-x[c](x=y))/13+2|0].repeat([d+26,-d,d,26-d][r])+0).join``para 111 bytes
Luke

Mais uma vez obrigado, @Luke. Antes de editá-lo, você prefere postar o texto acima como sua própria resposta? Eu sinto que difere suficientemente do meu (quase um híbrido dele e de Arnauld) para que tudo esteja bem.
Shaggy

Não, você pode editá-lo. Tentei jogar uma reducesolução, mas isso acabou sendo 115 bytes.
Lucas

2

C ++, 210 190 bytes

Minha primeira tentativa no golfe!

#include<iostream>
int g(char*a){char k,j,d;std::cout<<*a;a++;for(;*a;a++){for(j=*(a-1),d=j-*a,k=d>0?d>13?62:60:d<-13?60:62;j!=*a;j+=k-61,j=j<97?122:j>122?97:j)std::cout<<k;std::cout<<'*';}}

k armazena qual de <,> ou * imprimir. No início, ele simplesmente imprime o primeiro elemento da matriz e executa um loop para um do primeiro ao último elemento da matriz. j armazena o elemento anterior e, comparando se j mais perto de * a, <ou> defina k como <,> respectivamente e, em seguida, imprima k, execute esse loop até que j se torne igual a p. Depois de cada final do segundo loop, imprima *.


2
Bem vindo ao site! Se bem me lembro, *p!=0pode ser substituído por *p. Tenho certeza de que o espaço char *atambém é desnecessário. Você também precisará #include <iostream>e using namespace std;(embora eu ache que pode ser mais barato adicionar apenas std::) fazer desta uma resposta completa.
Assistente de trigo

2
Bem vindo ao site! Eu acho que você precisa incluir std::ou using namespace std;Você provavelmente também precisará #include <iostream>na sua contagem de bytes.
DJMcMayhem

+1, mas corrija as duas coisas acima mencionadas, bem-vindo ao PPCG;). Confira alguns dos idiomas do TIO Nexus ( tio.run/nexus ) quando tiver chance! Talvez se apresente a Dennis, ele é um cara importante flutuando por aqui.
Magic Octopus Urn

Obrigado a todos por sugestões e por apontar os erros. Vou atualizar o código em breve.
0x81915

1

05AB1E , 17 bytes

¬sÇ¥v„<>y0›èyÄ×ðJ

Experimente online!

Explicação

Usos >, <e <space>para denotar incremento , decremento , enviar

¬                  # get the first letter of the input string
 sǥ               # push a list of delta's of the character codes in the input string
    v              # for each delta
     „<>           # push the string "<>"
        y0›        # check if the delta is positive
           è       # use this to index into the string
            yÄ×    # repeat it abs(delta) times
               ðJ  # join to string with a space

E perdeu este por 3 horas 😉.
Magic Octopus Urn

1

Haskell , 167 168 126 bytes

f=fromEnum
r=replicate
a?b=mod(f a-f b-13)26-13
c#x=r(c?x)'<'++r(-c?x)'>'
s(c,s)x=(x,s++c#x++"*")
e(x:y)=x:snd(foldl s(x,[])y)

Agora, usando a solução aritmética do xnor. Ligue com e stronde str :: Stringestá a sequência a ser codificada.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.