Riduci la stringa in un frammento dell'alfabeto


25

Data una stringa non vuota composta solo da caratteri alfabetici minuscoli e maiuscoli e spazi ( [a-zA-Z ]), riducila a uno snippet dell'alfabeto, iniziando dal primo carattere.

Per ridurre una stringa, inizia con il primo carattere alfabetico, quindi rimuovi ogni carattere successivo che non sia la lettera successiva dell'alfabeto. Continua a farlo fino a raggiungere la fine della stringa.

Per esempio codegolf:

Inizia con c, rimuovi in oquanto non è la lettera successiva dell'alfabeto.
Mantieni dcome è la prossima lettera dell'alfabeto e mantieni ecome è anche la lettera successiva.
Rimuovere g, oe l, e mantenere f.

Il tuo frammento finale sarebbe quindi cdef

Regole

  • La capitalizzazione dovrebbe essere mantenuta, quindi CodEgolFsi tradurrebbe inCdEF
  • Lo spazio non è una lettera dell'alfabeto e quindi dovrebbe sempre essere rimosso, anche se è l'inizio della stringa
  • A causa della natura della riduzione, il primo carattere alfabetico dell'input sarà sempre il primo carattere dell'output.
  • zZè l'ultima lettera dell'alfabeto. Non ci sono lettere dopo, l'alfabeto non scorre.

Casi test

codegolf -> cdef
CodEgolf -> CdEf
 codeolfg -> cdefg
ProgrammingPuzzles -> P
Stack Exchange -> St
The quick red fox jumped over the lazy brown dog -> Tuvw
Zebra -> Z
Abcdegfhijkl -> Abcdef

punteggio

Questo è , quindi vince il minor numero di byte in ogni lingua !


Dal secondo ultimo caso di test, vedo che se raggiungiamo zCi fermiamo, giusto?
Mr. Xcoder,

@ Mr.Xcoder Corretto, vedere l'ultimo punto in "Regole"
Skidsdev il

2
Aggiungi un caso di test con uno spazio all'inizio. Come:<space>codegolf
Mr. Xcoder il

Posso restituire un array di lettere di output?
TheLethalCoder

1
@ Mr.Xcoder sì, puoi
Skidsdev il

Risposte:


12

JavaScript (ES6), 66 79 68 67 byte

f=([c,...s],p)=>c?(p?~parseInt(c+p,36)%37:c<'!')?f(s,p):c+f(s,c):''

Come?

Test di lettere consecutive

Poiché la conversione di due caratteri nei loro codici ASCII sarebbe un'operazione piuttosto lunga in JS, utilizziamo invece la seguente formula:

~parseInt(b + a, 36) % 37

A condizione che sia un e b sono [a-zA-Z ]l'espressione sopra come 0se e solo se un e b sono lettere consecutivi (cioè cifre consecutive in base 36), non importa il caso dei caratteri.

Per esempio:

~parseInt("Y" + "x", 36) = ~(36 * parseInt("Y", 36) + parseInt("x", 36))
                         = ~(36 * 34 + 33)
                         = -(36 * 34 + 33 + 1)
                         = -(37 * 34)

Formattato e commentato

f = ([c,                              // c = current character
         ...s],                       // s = array of remaining characters
                p) =>                 // p = previous matching letter
  c ? (                               // if there's still at least 1 character to process:
      p ?                             //   if p was already defined:
        ~parseInt(c + p, 36) % 37     //     test if p and c are NON-consecutive letters
      :                               //   else:
        c < '!'                       //     test if c is a space character
    ) ?                               //   if the above test passes:
      f(s, p)                         //     ignore c and keep the current value of p
    :                                 //   else:
      c + f(s, c)                     //     append c to the final result and update p to c
  :                                   // else:
    ''                                //   stop recursion

Casi test


7

Python 2 , 69 byte

lambda s:reduce(lambda x,y:x+y*((ord(y)-ord(x[~0]))%32==1),s.strip())

Provalo online!

Una semplice riduzione della stringa. Concateniamo semplicemente il personaggio successivo se e solo se (ord(y)-ord(x[~0]))%32==1. Controllo molto brutto - Sono sicuro che può essere migliorato, ma non sono sicuro di come!


Soluzione intelligente! Peccato che sia solo Python 2: P
Mr. Xcoder il

Puoi renderlo compatibile con Python 3 con from functools import*.
totalmente umano il

1
@ThomasWard totalmente umano stava solo dicendo agli altri come renderlo compatibile con Python 3. A proposito, import functools as fed f.è molto più lungo di from functools import*sicuro, anche usato una volta. Vedi questa discussione per maggiori informazioni.
Mr. Xcoder,

7

Python 3 , 75 85 84 91 81 77 75 byte

Penso che questo sia il più breve possibile in Python 3 . Può essere ridotto di alcuni byte in Python 2, come mostrato nell'invio di Sisifo .

  • EDIT: +10 per la correzione di un bug
  • EDIT: -1 correggendo un altro bug
  • EDIT: +7 per la correzione di un altro bug
  • MODIFICA: -10 byte con l'aiuto di @Ruud
  • EDIT: -4 byte poiché l'OP ci ha permesso di produrre le lettere separate da una nuova riga
  • EDIT: -2 byte grazie a @Ruud , tornando al conteggio dei byte originale!
s=input().strip();k=0
for i in s:
 if(ord(i)-ord(s[0]))%32==k:k+=1;print(i)

Provalo online!


Ho idee per migliorare, giocare a golf sul cellulare presto.
Mr. Xcoder,

2
81 byte . Le lettere maiuscole e minuscole si
adattano

@Ruud Queste sono esattamente le cose di cui stavo parlando nel mio commento, nella modifica.
Mr. Xcoder,


8
Sto aspettando che il downvoter spieghi le loro ragioni.
Mr. Xcoder,


4

Brachylog , 15 byte

;ṢxS⊇.ḷ~sẠ∧Sh~h

Provalo online!

Questo sarebbe 10 byte:, ⊇.ḷ~sẠ&h~hse non fosse per il vincolo "stringhe può iniziare con spazi" abbastanza poco interessante.

Spiegazione

;ṢxS               S is the Input with all spaces removed
   S⊇.             The Output is an ordered subset of the Input
     .ḷ            The Output lowercased…
        ~sẠ          …is a substring of "abcdefghijklmnopqrstuvwxyz"
           ∧
            Sh     The first char of S…
              ~h   …is the first char of the Output

Poiché questo è abbastanza dichiarativo, anche questo è molto lento.


Beh, almeno batte Jelly! E, a proposito, non credo che tu possa davvero superare questo ...
Erik the Outgolfer

3

MATL , 18 16 15 byte

Grazie a Mr.Xcoder per aver segnalato un errore, ora corretto

Xz1&)"t@hkd1=?@

Le lettere nell'output sono separate da nuove righe.

Provalo online! Oppure verifica tutti i casi di test (il codice a piè di pagina mostra tutte le lettere di output sulla stessa riga per chiarezza).

Spiegazione

Xz       % Implicitly input a string. Remove spaces
1&)      % Push first character and then the remaining substring
"        % For each
  t      %   Duplicate previous character
  @      %   Push current character
  h      %   Concatenate both characters
  k      %   Convert to lowercase
  d      %   Consecutive difference. Gives a number
  1=     %   Is it 1?
  ?      %   If so
    @    %     Push current char
         %   End (implicit)
         % End (implicit)
         % Display stack (implicit)

Hai dimenticato di rimuovere gli spazi quando sono all'inizio della stringa: lo spazio non è una lettera dell'alfabeto e quindi dovrebbe sempre essere rimosso, anche se è l'inizio della stringa .
Mr. Xcoder,

@ Mr.Xcoder Grazie! Corretto
Luis Mendo il


2

C # (Mono) , 129 107 93 91 87 byte

s=>{var r=s.Trim()[0]+"";foreach(var c in s)if(r[r.Length-1]%32==~-c%32)r+=c;return r;}

Salvato 2 byte grazie a @Mr. Xcoder.
Salvato 4 byte grazie a @jkelm.

Provalo online!


Non riesce negli spazi principali
Skidsdev il

@Mayube Woops non l'ha visto, risolto.
TheLethalCoder

2
91 byte . In linguaggi simili a C e Python, (c-1)%32è~-c%32
Mr. Xcoder il

1
87 byte Non è necessario riassegnare la stringa tagliata a causa dei controlli nel ciclo for
jkelm

2

PHP, 64 + 1 byte

while($c=$argn[$i++])$c<A||$n&&($c&_)!=$n||(print$c)&$n=++$c&__;

Esegui come pipe -nRo provalo online .


A parte i soliti trucchi: Quando $craggiunge Z, ++$csi traduce in AA,
e &__mantiene intatta quella lunghezza; quindi $nnon corrisponderà più $c.




2

Pyth, 21 20 18 byte

ef&qhThQhxGrT0tyr6

Provalo qui.

Versione molto più efficiente a 20 byte:

.U+b?t-CrZ1Creb1kZr6

Provalo qui.

-1 grazie a Mr. Xcoder (indirettamente).


Equivalente: .U+b?tlrreb1rZ1kZrz6(penso). Quel trucco mi ha aiutato però.
Mr. Xcoder,

@ Mr.Xcoder Se fosse un equivalente avrei potuto salvare un byte con, .U+b?tlrreb1rZ1kZr6ma sfortunatamente r <str> 6significa A.strip(), non rimuovere spazi bianchi non iniziali o finali.
Erik the Outgolfer,

Oh sì, non ho visto la tua soluzione fare affidamento su tutti gli spazi rimossi (il mio no)
Mr. Xcoder

@ Mr.Xcoder Umm, è necessario rimuovere tutti gli spazi.
Erik the Outgolfer,

No, non dovrei, poiché lo spazio ha un valore ASCII di 32, mentre tutte le lettere hanno > 64, e quindi non influiscono sulla funzionalità. Penso che questo valga anche per la tua risposta.
Mr. Xcoder,

1

Perl 6 , 51 byte

{S:i:g/\s|(\w){}<([<!before "{chr $0.ord+1}">.]+//}

Provalo

Allargato:

{  # bare block lambda with implicit parameter $_

  S                          # substitute implicitly on $_, not in-place
  :ignorecase
  :global
  /

    |  \s                    # match any space

    |  (\w)                  # match a word character
       {}                    # make sure $/ is updated (which $0 uses)

       <(                    # ignore everything before this

       [

           <!before "{       # make sure this won't match after this point
             chr $0.ord + 1  # the next ASCII character
           }">

           .                 # any character

       ]+                    # match it at least once

  //                         # remove what matched
}

Si noti che <!before …>è un'asserzione di larghezza zero



1

Japt , 18 17 16 byte

Salvato 1 byte grazie a @Shaggy

x
c
Çc %H¥V%H©V°

Provalo online!

Stavo pensando che sarebbe stato un po 'più breve, ma ... Tale è la vita ...

Spiegazione

x    First line: set U to the result.
x    Trim all spaces off of the input. Only necessary to remove leading spaces.

c    Second line: set V to the result.
c    Take the charcode of the first character in U.

 Ç   c %H¥ V%H© V°
UoZ{Zc %H==V%H&&V++}   Final line: output the result.
UoZ{               }   Filter to only the chars in Z where
    Zc                   the charcode of Z
       %H                mod 32
         ==V%H           equals V mod 32.
              &&V++      If true, increment V for the next letter.

Almeno più breve della mia parodia di 28 byte! : D Sembra che tu possa sostituirlo rScon x.
Shaggy,

1

C # (.NET Core) , 70 60 + 18 byte

-10 byte grazie a TheLethalCoder

a=>{var c=a.Trim()[0];return a.Where(x=>x%32==c%32&&++c>0);}

Il conteggio dei byte include anche:

using System.Linq;

Provalo online!

1 byte più lungo (attualmente) (non più) di TheLethalCoder in modo da pubblicare per divertimento. Approccio diverso, con LINQ.

Questo sfrutta due funzioni simili a C in C #: una charvariabile di carattere si comporta implicitamente come la stessa di un numero intero inte l'operatore booleano AND &&non esegue l'operazione corretta se left restituisce a false. Spiegazione del codice:

a =>                                  // Take string as input
{
    var c = a.Trim()[0];              // Delete leading spaces and take first letter
    return a.Where(                   // Filter out characters from the string, leaving those that:
               x => x % 32 == c % 32  // it's the next character in alphabet case-insensitive (thanks to modulo 32 - credits to previous answers)
               && ++c > 0             // If it is, go to the subsequent character in alphabet (and this always has to return true)
           );
}

Rimuovere .ToArray()restituendo come IEnumerable<char>per salvare byte.
TheLethalCoder

@TheLethalCoder giusto, ho appena visto il commento sotto la sfida. Grazie!
Grzegorz Puławski,

1

q / kdb +, 47 45 byte

Soluzione:

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}

Esempi:

q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"CodEgolf"
"CdEf"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}" codeolfg"
"cdefg"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"ProgrammingPuzzles"
"P"
q){"c"$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x}"The quick red fox jumped over the lazy brown dog"
"Tuvw"

Spiegazione:

Sfruttando il mod 32trucco dalle soluzioni esistenti insieme alla funzione di convergenza . Scorri sulla stringa, se la differenza tra l'ultimo elemento del risultato (ad es. Inizia con T"La volpe rossa veloce ...") e il carattere corrente è 1 (dopo essere stato modcon 32), quindi lo aggiungiamo a il risultato (quindi prendendo il motivo per cui prendiamo last x), quindi rimettere tutto su una stringa.

{10h$({(x;x,y)1=mod[y-last x;32]}/)7h$trim x} / the solution
{                                           } / lambda function
                                      trim x  / trim whitespace (leading/trailing)
                                   7h$        / cast string to ASCII (a -> 97)
     ({                         }/)           / converge
                    y-last x                  / y is the next item in the list, x contains results so far
              1=mod[        ;32]              / is the result mod 32 equal to 1
       (x;x,y)                                / if false, return x, if true return x concatenated with y
 10h$                                         / cast back to characters

1

Perl 5 , 30 + 1 (-n) = 31 byte

/$b/i&&(print,$b=++$_)for/\S/g

Provalo online!

Come?

/$b/i        # check if this letter equals the one in $b, ignore case
&&(print,    # output it if so
$b=++$_)     # store the next character to find
for/\S/g     # Looping over all non-whitespace characters

0

Retina , 76 byte

 

^.
$&$&$&¶
{T`@@L@l`@l@l@`..¶
T`l`L`.¶
(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

Provalo online! Il link include casi di test. Spiegazione:

 

Elimina spazi.

^.
$&$&$&¶

Triplica il primo carattere e inserisci un separatore.

{T`@@L@l`@l@l@`..¶
T`l`L`.¶

Converti il ​​secondo e il terzo carattere in minuscolo e incrementali. Converti quest'ultimo in maiuscolo. Questi sono ora i caratteri di ricerca.

(.)(.)((¶).*?(\1|\2)|¶.*)
$5$5$5$4

Prova ad abbinare uno dei caratteri di ricerca. Se trovato, quindi triplica la corrispondenza, che riavvia il ciclo per la ricerca successiva. Altrimenti, basta eliminare i caratteri di ricerca e il resto dell'input.


0

8 ° , 114 byte

Codice

: z dup n:1+ 32 bor >r "" swap s:+ . ; 
: f s:trim 0 s:@ z ( nip dup 32 bor r@ n:= if rdrop z then ) s:each rdrop ;

Spiegazione

: z             \ n -- (r: x)
                \ print letter and save on r-stack OR-bitwised ASCII code of following letter
  dup           \ duplicate item on TOS
  n:1+          \ get ASCII code of the following letter
  32 bor        \ bitwise OR of ASCII code and 32 
  >r            \ save result on r-stack
  "" swap s:+ . \ print letter
;

: f        \ s -- 
  s:trim   \ remove trailing whitespace
  0 s:@    \ get 1st letter
  z        \ print 1st letter and save on r-stack OR-bitwised ASCII code of following letter
  ( nip    \ get rid of index
    dup    \ duplicate item on TOS
    32 bor \ bitwise OR of current ASCII code and 32 
    r@     \ get value stored on r-stack
    n:=    \ compare values to see if letter is printable or not
    if 
      rdrop \ clean r-stack
      z     \ print letter and save on r-stack OR-bitwised ASCII code of following letter
    then 
  ) 
  s:each    \ handle each character in string
  rdrop     \ clean r-stack
;

Esempio

ok> " The quick red fox jumped over the lazy brown dog" f
Tuvw



0

Pyth, 15 byte

eo,}r0NG_xQhNty

Suite di test

A differenza di tutte le altre risposte, questo non unisce l'output, genera tutte le sottosequenze dell'input, quindi ordina loro di mettere la stringa desiderata alla fine e di emetterla.


Penso che devi controllare se anche la prima lettera dell'output è la prima lettera dell'input. E penso che l'ordine iniziale sia importante.
Erik the Outgolfer,

@EriktheOutgolfer Spiacente, stai dicendo che la risposta è sbagliata? Mi assicuro che la sequenza il cui primo carattere sia il primo nell'input tra tutte le sottosequenze in ordine alfabetico sia quella ordinata fino alla fine. Vedi il caso di test che inizia con uno spazio.
isaacg,

Puoi aggiungere una spiegazione per favore? Potrei aver frainteso o qualcosa del genere ...
Erik the Outgolfer,

0

J, soluzione parziale

Sto pubblicando questo per feedback e idee per il miglioramento più di ogni altra cosa. Funziona, ma non gestisce i casi di capitalizzazione e spazio, ed è già lungo per J.

Innanzitutto un verbo diadico helper che ti dice se gli argomenti destro e sinistro sono alfabeticamente adiacenti:

g=.(= <:)&(a.&i.)  NB. could save one char with u:

Successivamente un verbo che rimuove il primo elemento che non fa parte di una sequenza alfabetica a partire dal primo elemento:

f=.({~<^:3@>:@i.&0@(0,~2&(g/\))) ::]

Nota che utilizziamo Adverse ::per restituire l'intero argomento invariato se non viene trovato alcun elemento non-streak (ovvero, se l'intero argomento è una sequenza alfabetica valida).

Infine, la soluzione è data applicando ffino alla convergenza:

f^:_ 'codegolf'  NB. => 'cdef'

Provalo online!


Ed ecco una versione analizzata di fper una lettura più semplice:

           ┌─ ~ ─── {                         
           │                              ┌─ <
           │                       ┌─ ^: ─┴─ 3
           │                 ┌─ @ ─┴─ >:      
       ┌───┤           ┌─ @ ─┴─ i.            
       │   │     ┌─ & ─┴─ 0                   
       │   │     │                            
       │   └─ @ ─┤     ┌─ 0                   
── :: ─┤         │     ├─ ~ ─── ,             
       │         └─────┤                      
       │               │     ┌─ 2             
       │               └─ & ─┴─ \ ─── / ──── g
       └─ ]         

Domanda laterale : perché i caratteri del riquadro non si allineano perfettamente quando vengono visualizzati su SO (funzionano nella mia console):

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.