Riduci una stringa numerica


12

Data una stringa di 1e 2di qualsiasi lunghezza, scrivi un po 'di codice (non deve più essere una funzione , tutto andrà bene) che calcola quanti passaggi è necessario per ridurre la stringa in una forma finale, seguendo questo criterio:

Se la stringa è 112112, questo significa che si devono stampare un 1, due 1 e 2, come questo: 1112. Quando eseguirai di nuovo l'operazione, dovrai stampare 1 e 2 12. Quindi si stampa uno 2, ottenendo 2. Questa è una forma finale, poiché questa stringa non cambierà più. Il tuo codice verrà generato 3, poiché hai bisogno di 3 passaggi per arrivare al modulo finale.

Altre regole

  • Se la stringa ha una lunghezza irregolare, l'ultimo numero rimane invariato.

  • Ogni stringa che non può più cambiare (come 222222) è considerata una forma finale.

  • Non è possibile utilizzare alcuna fonte esterna.

  • Il codice deve funzionare con ogni stringa di 1e 2.

  • Vince il codice più corto, in quanto codice-golf.

  • Il tuo codice dovrebbe stampare ogni passaggio.

  • Ogni metodo di input andrà bene.

Esempi

Input >> 122122122121212212

Your code has to print:
211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps:7 (you can omit the "Steps")
---- ---- ---- ----
Input >> 22222221

Your code has to print:
22222211
2222221
2
---- ---- ---- ----
Input >> 2222

Your code has to print:
0

EDIT: fortemente modificato. Mi dispiace per quello.


3
"Se la tua stringa è 112112, ciò significa che devi stampare un 1, due 1 e un 2, in questo modo: 1112." Non capisco.
Fabinout,

7
Prova a leggerlo ad alta voce. È "uno uno", "due" e "uno due". Voglio dire, "1 volta 1", "2 volte 1" e "1 volta 2".
Vereos,

5
Se le regex "non sono nemmeno utili", perché le vietate?
JB

1
Restrizione di Regex rimossa.
Vereos,

1
@ProgramFOX "un 1, due 1s, ea 2": 1 11 2. Ogni due numeri è una coppia: il primo numero della coppia indica quante volte rendere il secondo numero nella coppia. Qualsiasi cifra dispari finale senza un partner di coppia viene visualizzata così com'è.
apsillers

Risposte:


7

Ruby 1.9+, 73 caratteri

Vedo la regola del non regex come sciocca e arbitraria, quindi ecco una soluzione basata sul regex dispettoso :

gets
($.+=1;puts$_.gsub!(/(.)(.)/){$2*$1.to_i})until~/^(22)*[12]?$/
p~-$.

Prova:

$ ruby 21.rb <<< 122122122121212212
211222111111222
11222111222
122111222
2111222
111222
1222
222
7

L'ultima riga è il numero di passaggi.

Modifica: la restrizione Regex è stata rimossa da Vereos.


3

C - 156 154

Il mio primo codice golf qui!

f(char*s,c){puts(s);char*a=s,*b=s,m=50,x,y;while(*a){
x=*a++;y=*a++;if(y)m&=x&y;*b++=y?:x;x-49?*b++=y:(*b=0);}
*b=*a;return m/50?printf("%i",c),c:f(s,c+1);}

Test:

char c[] = "12211122211222221";
f(c,0);

Produzione:

12211122211222221
21112211222221
111221222211
121122221
21222211
1122221
122221
22211
22111
2211
221
10

2

GolfScript: 69 caratteri

0\{\)\.p.[]\{~10base{.,1>{(\(@\{''+*}++~@\+\.}{~+0.}if}do;}~.@=!}do;(

Ogni iterazione del ciclo interno trova i primi 2 numeri nella stringa e li usa per formare un blocco del modulo {num1 num2 '' + *}. Quando questo blocco viene valutato, otteniamo la lettura desiderata di quei numeri. Ripeti fino a quando non ci sono più caratteri. Quindi, ripeti quel ciclo tenendo traccia del numero di iterazioni e stampe.

Campione:

echo '12211122211222221' | ruby golfscript.rb g.gs
"12211122211222221"
"21112211222221"
"111221222211"
"121122221"
"2122221"
"1122221"
"122221"
"22211"
"22111"
"2211"
"221"
10

2

Python - 126

def f(s):
 j=0
 while 1:
    n="";i=0
    for c in s:n+=c*i;i=[int(c),0][i>0]
    if i:n+=`i`
    if s==n:break
    s=n;print s;j+=1
 print j

Questo non stampa il valore di input. Se necessario, passa print s;a priman="";

Nota: hai detto "funzione", quindi questa è una funzione. Ecco una versione che non è una funzione (127 caratteri):

s=raw_input();j=0
while 1:
    n="";i=0
    for c in s:n+=c*i;i=[int(c),0][i>0]
    if i:n+=`i`
    if s==n:break
    s=n;print s;j+=1
print j

(Se posso avere l'utente incolla il numero in poi 118 (incolla i dati tra virgolette sulla prima riga)):

s="";j=0
while 1:
    n="";i=0
    for c in s:n+=c*i;i=[int(c),0][i>0]
    if i:n+=`i`
    if s==n:break
    s=n;print s;j+=1
print j

Esecuzione di esempio:

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Come bonus, ognuna di queste soluzioni funziona per stringhe contenenti numeri più grandi (fino a 9), ma alcune stringhe producono output sempre più grandi (ad esempio, 99)


1

JavaScript, 107

(richiede il supporto della funzione freccia, ad esempio come in Firefox)

for(p=prompt,s=p(),k=0;r=s.match(/.?.?/g).map(a=>a>2?a[1]+(a<13?'':a[1]):a).join(''),p(s),r!=s;s=r)k++;p(k)
  • s è la stringa di input

  • Ad ogni round, usiamo la regex .?.?per esplodere sin una matrice di stringhe di due caratteri, quindi mapquelle stringhe nelle loro forme ridotte e incolliamo nuovamente la matrice

  • r memorizza il risultato del round corrente per il confronto con il precedente s

  • k è il contatore rotondo

  • Abusiamo orribilmente prompt(alias p) come meccanismo di input e output, poiché può presentare un messaggio all'utente


for(p=prompt,s=p(),k=0;
    r=s.match(/.?.?/g).map(
        a=>
            a>2?                     // if a is more than one char
                a[1]+(a<13?'':a[1])  // double the second char if the first char is 2
               :a                    // if not two chars, return a
    ).join(''),                      // glue new array together
     p(s),                           // print s
     r!=s;                           // test if string has changed
    s=r)
        k++;
p(k)

1

Perl - 50 (+2) byte

$a-=print while"$_"ne(s/(.)(.)/$2x$1/ge,$_);$_=-$a

Richiede -plopzioni della riga di comando.

Esempio di utilizzo:

$ more in.dat
122122122121212212

$ perl -pl rev-count.pl < in.dat
211222111111222
11222111222
122111222
2111222
111222
1222
222
7

$ more in.dat
22222221

$ perl -pl rev-count.pl < in.dat
22222211
2222221
2

$ more in.dat
2222

$ perl -pl rev-count.pl < in.dat
0

1

PHP, 240

<?php
$s=$_GET['i'];$h=$s;for($t=1;$h!=r($h);$t++){echo$h.'<br>';$h=r($h);}echo r($s)==$s?0:$h.'<br>'.$t;function r($c){for($i=0;$i<strlen($c)-1;$i+=2){$s.=$c[$i]==1?$c[$i+1]:$c[$i+1].$c[$i+1];if($i+3==strlen($c))$s.=$c[$i+2];}return$s;}?>

Esempio: http://skyleo.de/codegolf.php?i=211222111111222

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Sono un pò cattivo con codegolf ._. Forse non dovrei usare solo Java e PHP (e dovrei pensare più complicato)


1
CodeGolf non si tratta di trovare la soluzione più complicata, ma piuttosto la più semplice.
primo

Non hai davvero bisogno di farlo str_splitpoiché puoi accedere a singoli caratteri in una stringa proprio come un array in PHP.
Gareth,

Sì, dopo qualche tempo ho pensato a me stesso, ma ero troppo pigro per modificarlo. Ma ora l'ho cambiato.
Leo Pflug,

0

R, 158

s=utf8ToInt(scan(,""))-48;i=0;while(any(!!s-2)){t=(a<-sum(s|T))%%2;u=s[seq(a-t)];cat(s<-c(rep(u[c(F,T)],u[c(T,F)]),s[a*t]),"\n",sep="");i=i+1};cat("Steps:",i)

Esempio:

122122122121212212

211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps: 7

0

MATEMATICA, 117

s="122122122121212212";
Grid@FixedPointList[(Partition[#,2,2,1,{}]/.{{1,1}->{1},{1,2}->{2},{2,1}->{1,1}}//Flatten)&,FromDigits/@Characters@s]

122122122121212212
211222111111222
11222111222
122111222
2111222
111222
1222
222
222

0

POWERSHELL, 2

Sulla base della risposta di Vereos "Puoi usare qualunque metodo di input accorcia il tuo codice" alla mia domanda nei commenti dell'OP, il seguente script ottiene il risultato:

$a

Esempio eseguito per "122122122121212212":

# Input method is to assign answer to $a:
$a = @"
211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps: 7
"@

# Execute script
$a

# Answer follows:
211222111111222
11222111222
122111222
2111222
111222
1222
222

Ovviamente questa non è una voce seria - il suo scopo è quello di illustrare il mio punto che consentire qualsiasi metodo di input può banalizzare il codice effettivo necessario per produrre la risposta. Quindi il metodo di input deve essere specificato in modo più rigoroso.


0

J, 41 caratteri

Come funzione (ew parens! Non terribilmente felice per loro):

(,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:)
Vista esplosa
                _2&(            )\          NB. on non-overlapping 2-grams:
                       (      )/            NB.   insert between the two chars:
                        ".@[                NB.     read left operand ([) as a number
                            #]              NB.     and repeat right this many times,
                    <@(           )         NB.   then put it in a box
            ([:;                   )        NB. open and concatenate the boxes
           (                        ^:a:)   NB. repeat until fixpoint (keeping intermediates)
        }:@                                 NB. drop first element (the input)
(,":@#)@                                    NB. append length of array (# steps)
Esecuzione del campione
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '1121121'
1121121
11121  
121    
21     
11     
5      
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '122122122121212212'
122122122121212212
211222111111222   
11222111222       
122111222         
2111222           
111222            
1222              
7                 

0

Perl, 107 caratteri

L'altro codice perl batte chiaramente questo, ma per quello che vale, eccolo qui. Ho usato l'opzione -l al costo di un personaggio in più:

$_=<>;while(1){$l=$_;$_=join"",map{($a,$b)=split//;$b?$b x$a:$a}grep/./,split/(..?)/;last if$l eq$_;print}

Una versione più leggibile di questo:

$x = <>; while(1) { $l = $x; $x = join "", map{ ($a,$b) = split//, $_; $b ? $b x $a: $a } grep /./, split /(..?)/, $x; last if $l eq $x; print $x}
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.