Praming Puzles & Colf: Menyingkat String

25

Setelah menghabiskan waktu di situs ini saya datang untuk menikmati hal-hal sesingkat mungkin. Itu mungkin alasan mengapa saya baru-baru ini agak tersinggung oleh string yang berisi karakter yang sama lebih dari sekali. Tugas Anda adalah menulis fungsi atau program yang mengembunkan string yang diberikan sesuai dengan aturan berikut:

  • Mulailah dengan 0-kondensasi , yaitu mencari pasangan pertama (paling kiri) dari karakter yang sama dengan 0 karakter lain di antara mereka. Jika pasangan seperti itu ditemukan, hapus salah satu dari dua karakter dan nyalakan kembali algoritma dengan melakukan kondensasi 0 lainnya . Jika tidak ada pasangan yang ditemukan, lanjutkan ke langkah berikutnya. Contoh:
    programming-C0-> programing
    aabbcc-C0-> abbcc
    test-C0->test

  • Kemudian lakukan kondensasi 1 , yaitu mencari pasangan pertama dari karakter yang sama dengan 1 karakter lainnya di antara mereka. Jika pasangan semacam itu ditemukan, hapus salah satu dari mereka dan semua karakter di antara mereka dan mulai kembali dengan 0-kondensasi . Jika tidak ada pasangan yang ditemukan, lanjutkan ke langkah berikutnya. Contoh:
    abacac-C1-> acac
    java-C1->ja

  • Lanjutkan dengan 2-kondensasi dan seterusnya hingga n-kondensasi dengan n menjadi panjang string asli, setiap kali restart setelah kondensasi menghapus beberapa huruf. Contoh:
    programing-C2-> praming
    abcdafg-C3->afg

String yang dihasilkan disebut kental dan berisi setiap karakter paling banyak satu kali.


Memasukkan:

String huruf kecil dari ascii-karakter yang dapat dicetak.

Keluaran:

The kental tali sesuai dengan aturan di atas.

Contoh:

examples     -> es
programming  -> praming
puzzles      -> puzles
codegolf     -> colf
andromeda    -> a
abcbaccbabcb -> acb
if(x==1):x++ -> if(x+
fnabnfun     -> fun
abcdefae     -> abcde

Contoh terperinci untuk memperjelas cara kerja algoritma:

fnabnfun -C0-> fnabnfun -C1-> fnabnfun -C2-> fnfun -C0-> fnfun -C1-> fun -C0-> fun 
 -C1-> fun -C2-> ... -C8-> fun

abcbaccbabcb -C0-> abcbacbabcb -C0-> abcbacbabcb -C1-> abacbabcb -C0-> abacbabcb 
 -C1-> acbabcb -C0-> acbabcb -C1-> acbcb -C0-> acbcb -C1-> acb -C0-> acb 
 -C1-> ... -C12-> acb

Pendekatan Anda tidak harus mengimplementasikan algoritma dari atas selama solusi Anda dan algoritma mengembalikan output yang sama untuk semua input yang diizinkan. Ini adalah tantangan .


Terima kasih kepada @Linus untuk komentar kotak pasir yang bermanfaat!

Laikoni
sumber
@MartinEnder Riley masih diperlukan, karena itu satu-satunya solusi Retina saya yang tidak berfungsi.
mbomb007
@ mbomb007 Ah, begitu. Poin bagus.
Martin Ender
Apakah string input akan berisi karakter yang tidak dapat dicetak seperti spasi?
mbomb007
@ mbomb007 Tidak, menganggap karakter ascii yang dapat dicetak hanya baik-baik saja.
Laikoni
@ mbomb007 Namun sejauh yang saya tahu, ruang yang dianggap sebagai karakter ascii dicetak, misalnya di sini .
Laikoni

Jawaban:

6

JavaScript (ES6), 74 byte

f=
(s,n=0,m=s.match(`(.).{${n}}\\1`))=>s[n]?m?f(s.replace(...m)):f(s,n+1):s
;
<input oninput=o.textContent=f(this.value)><pre id=o>

Neil
sumber
Sangat bagus, lebih pendek dari apa yang saya pikirkan.
ETHproduk
5

Perl, 38 31 30 29 byte

Ini harus meninggalkan bahasa non-golf jauh di belakang ...

-1 untuk $-[0]terima kasih kepada Riley

-1 untuk @{-}terima kasih kepada Dada

Termasuk +1 untuk -p

Berikan masukan pada STDIN

condense.pl:

#!/usr/bin/perl -p
s/(.)\K.{@{-}}\1// while/./g

Versi 27 byte ini seharusnya berfungsi tetapi tidak karena perl tidak melakukan interpolasi @-dalam regex (lihat /programming/39521060/why-are-etc-not-interpolated-in-strings )

#!/usr/bin/perl -p
s/(.)\K.{@-}\1// while/./g
Ton Hospel
sumber
Bagaimana cara @{\@-}kerjanya? Saya pikir @-memegang indeks setiap pertandingan, jadi bagaimana cara "menghitung" pada setiap iterasi. Juga, jika Anda mencetak @{\@-}sebelum dan setelah setiap penggantian hanya mencetak 1 atau 2.
Riley
1
@Riley /./gProgres dengan 1 dalam string setiap kali, kecuali ketika string berubah, maka itu reset ke 0. Jika Anda mencetak @-setelah /./gtetapi sebelum s///Anda akan melihatnya naik (gunakan tes di mana string yang tersisa cukup besar)
Ton Hospel
Pencetakan $-[0]memberi angka yang saya harapkan. Apakah @{\@-}bertindak seperti $-[0]karena konteks regex tetapi tidak saat mencetak karena alasan tertentu? $-[0]byte lebih pendek daripada @{\@-}jika mereka sama.
Riley
"@{\@-}"tidak sama dengan @{\@-}(tanpa ").
Riley
@Riley Tidak, tetapi "@{\@-}"sama dengan "@-". Dan ini juga harus benar untuk penggantian regex tetapi tidak. Secara simultan $-[0]harus bekerja tetapi tidak. PS: Anda mungkin entah bagaimana memiliki konteks skalar yang diterapkan @-ketika Anda mencetak, jadi Anda selalu mendapat 1 atau 2
Ton Hospel
3

CJam , 35 byte

rL{_,{{(_@_@#I={I)>]sj}*}h]s}fI}j

Cobalah online!


rL{                            }j   | run recursion on input
   _,{                      }fI     | for I from 0 to length(input)
      {                 }h]s        | one pass & clean up
       (_@                          | slice and store leading element A
          _@#I={      }*            | if next A is I steps away
                I)>                 | slice off I+1 element
                   ]sj              | clean up & recursion

Anda dapat melihat masing-masing kondensasi dengan memasukkaned

Linus
sumber
2

Python 2, 117 104 101 byte

Secara rekursif melakukan penggantian yang diperlukan. Saya membangun regex secara dinamis.

import re
def f(s,i=0):t=re.sub(r"(.)%s\1"%("."*i),r"\1",s);e=s==t;return i>len(t)and t or f(t,i*e+e)

Cobalah online

mbomb007
sumber
Dua baris kembali dapat diringkas menjadi return i>len(t) and t or s!=t and f(t) or f(t,i+1)jaring -4 byte
Quelklef
2 byte lainnya dapat dicukur dengan mengubahnya menjadireturn t if i>len(t)else s!=t and f(t)or f(t,i+1))
Quelklef
Bahkan lebih jauh dengan e=s==t;return i>len(t)and t or f(t,i*e+e)dan kemudian Anda dapat menghapus i=0definisi fungsi, tetapi Anda harus memanggil dengan 0 mulai.
Quelklef
Saya akan berasumsi bahwa keempat spasi di sana bukan karena Anda menggunakan empat spasi tetapi karena SE secara otomatis memperluasnya. Jika bukan itu masalahnya, Anda dapat mengubah semua spasi menjadi tab atau satu spasi untuk -9 byte.
Dana Gugatan Monica
@Quelklef Meta melarang mengambil parameter tambahan.
mbomb007
1

Perl 53 52

Termasuk +1 untuk -p

for($i=0;$i<length;){$i=(s/(.).{$i}\1/\1/)?0:$i+1;}

Cobalah di ideone .

Riley
sumber
1

Mathematica, 101 byte

NestWhile[i=0;StringReplace[#,a_~~_~RepeatedNull~i++~~a_:>a,1]&,#,SameQ,2,ByteCount@#]&~FixedPoint~#&

Harus ada cara untuk membuat ini lebih pendek ...

JungHwan Min
sumber
1

PHP, 90 Bytes

for($s=$argv[$c=1];$s[$i=++$i*!$c];)$s=preg_replace("#(.).{{$i}}\\1#","$1",$s,1,$c);echo$s;

atau 92 Bytes

for($s=$argv[1];$s[$i];$i=++$i*!$c)$s=preg_replace("#(.).{".+$i."}\\1#","$1",$s,1,$c);echo$s;   
Jörg Hülsermann
sumber
1
1) versi pertama: +$ibukannya $i+=0(-2). 2) forlingkaran bukannya whiledapat menyimpan dua byte dan memungkinkan untuk menghapus keriting (-4). 3) $i=++$i*!$cbukannya $i=$c?0:$i+1(-1). 4) \\2tidak diperlukan, hapus tanda kurung (-2). 5) Anda dapat membiarkan batas 9alih-alih 1untuk kecepatan (+0)
Titus
@Titus ide yang sangat bagus. Saya belum melihat ini Terima Kasih
Jörg Hülsermann
Sekarang saya berpikir lagi ... +$itidak berfungsi dalam setiap kasus. Coba hammer. PHP tidak mengeluh tentang kawat gigi kosong di regex; tapi itu tidak sesuai dengan yang diinginkan. Ngomong-ngomong: Saya menghitung 91, bukan 90. Tapi coba yang baru 1)for($s=$argv[$c=1];$s[$i=++$i*!$c];)
Titus
@Itus Ya memang saya kembali ke $i+=0dan akan mencoba proposal Anda nanti. Apa yang dimaksud dengan palu?
Jörg Hülsermann
@Titus oke masalah yang sama jika puzzleatau sesuatu yang lain seperti (.)//1tapi tidak apa-apa dengan proposal Anda atau$i´=0
Jörg Hülsermann
1

Ruby, 75 64 57 byte

(56 byte popsi kode + baris perintah.)

Menggunakan interpolasi string di dalam regex untuk mengontrol panjang kecocokan yang diganti.

i=0
~/(.).{#{i}}\1/?sub($&,$1)&&i=0: i+=1while i<$_.size

Uji:

$ ruby -p condense.rb <<< fnabnfun
fun
daniero
sumber
1

Haskell , 97 88 bytes

(0?)
(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s<m=s|a<-s!drop m s=sum[m+1|a==s]?a

Cobalah online!


Bersion lama 97 byte:

(a:s)!(b:t)|a==b=a:t|1<3=a:s!t
s!_=s
m?s|length s==m=s|a<-s!drop m s=(last$0:[m+1|a==s])?a
c=(0?)

Cobalah di ideone .

Penjelasan:

(a:s)!(b:t)|a==b = a:t         --perform condensation
           |1<3  = a:s!t       --recursively compare further
 s   ! _         = s           --no condensation performed

The (!)melakukan fungsi satu n-kondensasi ketika diberi string sekali utuh dan sekali dengan n karakter pertama dihapus, misalnya abcdbe, dan cdbeuntuk 2-kondensasi, oleh rekursif membandingkan dua karakter utama.

m?s|length s==m   = s         --stop before performing length-s-condensation
   |a <- s!drop m s           --a is the m-condensation of s
    = (last$0:[m+1|a==s])?a   --disguised conditional:
                              -- if a==s       if the m-condensation did not change s
                              -- then (m+1)?a  then perform m+1-condensation
                              -- else 0?a      else restart with a 0-condensation

c=(0?)                        -- main function, initialise m with 0
Laikoni
sumber