Zmniejsz ciąg liczbowy

12

Biorąc pod uwagę ciąg 1i 2dowolnej długości, napisać trochę kodu (nie musi być funkcji już wszystko będzie dobrze), który oblicza, ile kroków to trzeba zmniejszyć ciąg do ostatecznej formie, w następstwie tego kryterium:

Jeśli łańcuch jest 112112, oznacza to, że trzeba wydrukować 1, dwie 1s i 2, podobnie jak to: 1112. Kiedy ponownie wykonasz operację, będziesz musiał wydrukować 1 i 2. Dostajesz 12. Następnie drukujesz jeden 2, otrzymując 2. To jest ostateczna forma, ponieważ ten ciąg nie będzie się już zmieniać. Twój kod wyświetli się 3, ponieważ potrzebujesz 3 kroków, aby przejść do ostatecznego formularza.

Inne zasady

  • Jeśli ciąg ma nierówną długość, ostatni numer pozostaje nietknięty.

  • Każdy ciąg znaków, który nie może się już zmienić (jak 222222), jest uważany za formę ostateczną.

  • Nie możesz użyć żadnego zewnętrznego źródła.

  • Twój kod musi działać z każdym ciągiem 1i 2.

  • Wygrywa najkrótszy kod, ponieważ jest to golf golfowy.

  • Twój kod powinien być drukowany na każdym kroku.

  • Każda metoda wprowadzania będzie w porządku.

Przykłady

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

EDYCJA: Mocno edytowana. Bardzo mi przykro z tego powodu.

Vereos
źródło
3
„Jeśli twój ciąg to 112112, oznacza to, że musisz wydrukować 1, dwa 1 i 2, takie jak: 1112.” Nie rozumiem.
Fabinout
7
Spróbuj przeczytać to na głos. To „jeden”, „dwa” i „jeden dwa”. Mam na myśli „1 raz 1”, „2 razy 1” i „1 raz 2”.
Vereos
5
Jeśli wyrażenia regularne są „nawet nieużyteczne”, dlaczego je banujesz?
JB
1
Usunięto ograniczenie Regex.
Vereos
1
@ProgramFOX "jednym 1, dwie 1s i 2": 1 11 2. Co dwie liczby są parą: pierwsza liczba pary mówi, ile razy ma być renderowana druga liczba w parze. Każda ostatnia cyfra nieparzysta bez partnera pary jest renderowana w stanie „jak jest”.
apsillers

Odpowiedzi:

7

Ruby 1.9+, 73 znaki

Widzę regułę no-regex jako głupią i arbitralną, więc oto złośliwe rozwiązanie oparte na wyrażeniach regularnych:

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

Testowe uruchomienie:

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

Ostatni wiersz to liczba kroków.

Edycja: Ograniczenia Regex zostały usunięte przez Vereos.

daniero
źródło
3

C - 156 154

Mój pierwszy golf golfowy tutaj!

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

Wynik:

12211122211222221
21112211222221
111221222211
121122221
21222211
1122221
122221
22211
22111
2211
221
10
tia
źródło
2

GolfScript: 69 znaków

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

Każda iteracja wewnętrznej pętli znajduje pierwsze 2 liczby w ciągu i używa ich do utworzenia bloku formularza {num1 num2 '' + *} . Gdy ten blok jest oceniany, otrzymujemy pożądany odczyt tych liczb. Powtarzaj to, dopóki nie będzie więcej znaków. Następnie powtórz tę pętlę, śledząc liczbę iteracji i drukowania.

Próba:

echo '12211122211222221' | ruby golfscript.rb g.gs
"12211122211222221"
"21112211222221"
"111221222211"
"121122221"
"2122221"
"1122221"
"122221"
"22211"
"22111"
"2211"
"221"
10
Ben Reich
źródło
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

To nie drukuje wartości wejściowej. Jeśli to konieczne, przejdź print s;do wcześniejn="";

Uwaga: powiedziałeś „funkcja”, więc jest to funkcja. Oto wersja, która nie jest funkcją (127 znaków):

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

(Jeśli mogę zmusić użytkownika do wklejenia numeru, to 118 (wklej dane między cudzysłowami w pierwszym wierszu)):

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

Przykładowy przebieg:

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Jako bonus, każde z tych rozwiązań działa dla ciągów zawierających większe liczby (do 9), ale niektóre ciągi dają coraz większe wyniki (na przykład 99)

Justin
źródło
1

JavaScript, 107

(wymaga obsługi funkcji strzałek, np. jak w 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 jest łańcuchem wejściowym

  • W każdej rundzie używamy wyrażenia regularnego, .?.?aby eksplodować sw tablicy ciągów dwuznakowych, a następnie maptych ciągów w postaci zredukowanej i skleić tablicę z powrotem

  • r przechowuje wynik bieżącej rundy do porównania z poprzednią s

  • k to okrągły licznik

  • Strasznie nadużywamy prompt(alias do p) jako mechanizmu wejściowego i wyjściowego, ponieważ może on przekazać wiadomość użytkownikowi


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)
apsillery
źródło
1

Perl - 50 (+2) bajtów

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

Wymaga -plprzełączników wiersza poleceń.

Przykładowe użycie:

$ 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
primo
źródło
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;}?>

Przykład: http://skyleo.de/codegolf.php?i=211222111111222

211222111111222
11222111222
122111222
2111222
111222
1222
222
7

Jestem trochę zły w codegolf ._. Może nie powinienem używać tylko Javy i PHP (i powinienem myśleć bardziej skomplikowany)

Leo Pflug
źródło
1
CodeGolf nie polega na znalezieniu najbardziej skomplikowanego rozwiązania, ale raczej najprostszym.
primo
Tak naprawdę nie musisz tego robić, str_splitponieważ możesz uzyskać dostęp do poszczególnych znaków w łańcuchu, tak jak tablica w PHP.
Gareth
Tak, po pewnym czasie pomyślałem, że sam, ale byłem zbyt leniwy, aby to edytować. Ale teraz to zmieniłem.
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)

Przykład:

122122122121212212

211222111111222
11222111222
122111222
2111222
111222
1222
222
Steps: 7
Sven Hohenstein
źródło
0

MATEMATYKA, 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
Murta
źródło
0

POWERSHELL, 2

Na podstawie odpowiedzi Vereos „Możesz użyć dowolnej metody wprowadzania, która skraca kod” na moje pytanie w komentarzach PO, następujący skrypt osiąga wynik:

$a

Przykład uruchomienia dla „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

Oczywiście nie jest to poważny wpis - jego celem jest zilustrowanie mojej tezy, że zezwolenie na dowolną metodę wprowadzania danych może trywializować rzeczywisty kod potrzebny do uzyskania odpowiedzi. Dlatego metoda wprowadzania danych musi być bardziej rygorystycznie określona.

użytkownik2460798
źródło
0

J, 41 znaków

Jako funkcja (ew parens! Niezbyt się z tego cieszę):

(,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:)
Widok rozstrzelony
                _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)
Przykładowy przebieg
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '1121121'
1121121
11121  
121    
21     
11     
5      
   (,":@#)@}:@(([:;_2&(<@((".@[#])/)\))^:a:) '122122122121212212'
122122122121212212
211222111111222   
11222111222       
122111222         
2111222           
111222            
1222              
7                 
Robaczek świętojański
źródło
0

Perl, 107 znaków

Drugi kod perla wyraźnie to bije, ale tutaj warto. Użyłem przełącznika -l kosztem dodatkowego znaku:

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

Bardziej czytelna wersja tego:

$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}
skibrianski
źródło