Son eklerim ne tür?


10

giriş

Böylece son ek sıralama algoritmalarını araştırarak, yeni fikirleri elle ve kodla değerlendirerek zamanımı boşa harcıyorum. Ama her zaman eklerimin türünü hatırlamak için mücadele ediyorum! Son eklerimin ne tür olduğunu söyleyebilir misiniz?

En çok ne kaldı?

Bir çok sonek sıralama algoritması (SAIS, KA, kendi daware'im) grubu, bunları sıralamak için farklı türlere ekler. İki temel tip vardır: S-tipi ve L-tipi sonekler. S-tipi sonekler , aşağıdaki sonekten sözlükbilimsel olarak daha az ( S maller) ve sözlükbilimsel olarak daha büyükse L-tipi ( L arger) soneklerdir. Bir sol-en S-tipi ( LMS-tipi ) sadece ki: A S-tipi bir önce geldiği son ek L-tipi son eki.

Bu LMS tipi soneklerle ilgili özel şey , bunları sıraladıktan sonra diğer tüm sonekleri doğrusal zamanda sıralayabilmemizdir! Harika değil mi?

Meydan okuma

Bir dize verildiğinde, bu dizedeki diğer karakterlerden daha az özel bir karakterle sonlandığını varsayalım (örneğin, boş bayttan bile küçük). Her son ek için bir tür aşındırıcı karakter çıktısı alın.

Özgürce hangi türü için kullanılacak karakter seçebilir ama tercih ediyorum L, S and *için L-, S- and LMS-typesürece oldukları gibi tüm yazdırılabilir ( 0x20 - 0x7E).

Misal

Dize mmiissiissiippiçıktısı verildiğinde (kullanırken L, S and *):

 LL*SLL*SLL*SLLL

Örneğin birincisi L, mmiissiissiippi$sözlükbilimsel olarak büyük olandan kaynaklanmaktadır miissiissiippi$( $eklenen minimum karakteri temsil eder):

L - mmiissiissiippi$ > miissiissiippi$
L - miissiissiippi$  > iissiissiippi$
* - iissiissiippi$   < issiissiippi     and preceeded by L
S - issiissiippi$    < ssiissiippi$
L - ssiissiippi$     > siissiippi$
L - siissiippi$      > iissiippi$
* - iissiippi$       < issiippi$        and preceeded by L
S - issiippi$        < ssiippi$
L - ssiippi$         > siippi$
L - siippi$          > iippi$
* - iippi$           < ippi$            and preceeded by L
S - ippi$            < ppi$
L - ppi$             > pi$
L - pi$              > i$
L - i$               > $

Bazı örnekler:

"hello world" -> "L*SSL*L*LLL"
"Hello World" -> "SSSSL*SSLLL"
"53Ab§%5qS"   -> "L*SSL*SLL"

Hedef

Peter Cordes'ı kızdırmak için burada değilim (bunu bir zamanlar yığın akışı üzerinde yapacağım); Bu yüzden elbette golfü çok tembelim ! Bayt cinsinden en kısa cevap kazanır.


Düzenleme: Karakterlerin sırası bayt değerlerine göre verilir. Yani karşılaştırma C'ler gibi olmalı strcmp.

Edit2: Yorumlarda belirtildiği gibi çıktı her girdi karakteri için tek bir karakter olmalıdır. Ben "bir dize döndür" olarak anlaşılacağı varsayılırken, en az 1 cevap tek karakterlerin bir listesini döndürür gibi görünüyor. Mevcut cevapları geçersiz kılmamak için tek karakterlerin (veya yazdırıldığında sadece 1 karakterle sonuçlanan tam sayıların) bir listesini döndürmenize izin vereceğim.


Doğrusal zaman için ipuçları:

  1. 2 paralel ileri yineleme veya tek bir geriye dönük yineleme ile yapılabilir.
  2. Her son ekin durumu yalnızca ilk 2 karaktere ve ikincisinin türüne bağlıdır.
  3. Girişi ters yönde tarayarak L veya S'yi şu şekilde belirleyebilirsiniz: $t=$c<=>$d?:$t(PHP 7), önceki ve önceki türün $cgeçerli karakteridir .$d$t
  4. PHP cevabımı görün . Yarın ödülü vereceğim.

Bu benim ilk sorum :) Sandbox iki upvotes ve yorum var, bu yüzden onun gönderilmeye hazır olduğunu düşünüyorum. Öneride bulunmaktan çekinmeyin!
Christoph

Girişte hangi karakterler görünebilir?
Martin Ender

Dizenizin desteklediği tüm karakterlerin altında, örneğin c++stil dizeleri için boş bayt bile . Bunu ikili veri olarak düşünün.
Christoph

Ne anlama *geliyor?
Leaky Nun

@LeakyNun *, karşılık gelen sonek türünde olduğu anlamına gelir left most s-type. A S-type suffix that is preceeded by a L-type suffix..
Christoph

Yanıtlar:


7

Haskell , 64 53 48 42 bayt

(0!)
k!(x:y)|x:y>y=1:2!y|2>1=k:0!y
_![]=[]

Çevrimiçi deneyin!

Ungolfed, Charyerine Int:

suffixes :: String -> String
suffixes = go 'S'
 where
   go :: Char -> String -> String
   go _ "" = ""
   go lorstar s | s > tail s = 'L' : go '*' (tail s)
                | otherwise  = lorstar : go 'S' (tail s)

Anonim işlevlere izin verilir, bu nedenle z=kaldırılabilir.
Ørjan Johansen

Haskell'i okuyamıyorum. Bana kısa bir açıklama yapmak ister misiniz?
Christoph

1
@Christoph: gofonksiyon iki argüman alır. Birincisi, Sdurumu tanımlamak için neyin kullanılması gerektiğini temsil eden karakterdir . İkincisi bir dizedir. Her adımdaki ilk karakteri kaldırarak bu dizeyi yinelemeli olarak geçer (işte budur tail). İşin püf noktası, ilk argümanın *önceki sonucun a Lveya Sbaşka bir değere ayarlanmış olmasıdır . Bu şekilde, a *veya a Skullanılması gerektiğinde, bu ilk argüman doğrudan kullanılabilir. Umarım mantıklıdır.
bartavelle

Bu oldukça iyi bir fikir! Daha akıllı fikirler görmeyi umuyorum :)
Christoph

@ ØrjanJohansen Sonucu TIO'da nasıl hazırlamam gerekir?
bartavelle

6

Jöle ,  25 23 21 20  19 bayt

Ṛ;\UỤỤIṠµI2n×ịØDṚ;0

Aşağıdakileri kullanarak karakter listesini basan tam bir program:

L: 0
S: 8
*: 9

(Bağlantı olarak, sonuncusu hariç tüm öğelerin sıfır olduğu bir öğe olduğu bir liste döndürür.)

Çevrimiçi deneyin! veya test paketine bakın(dönüştürerekLS*).

Nasıl?

Ṛ;\UỤỤIṠµI2n×ịØDṚ;0 - Link: list of characters, s  e.g. "cast"
Ṛ                   - reverse                           "tsac"
  \                 - cumulative reduce by:
 ;                  -   concatenation                   ["t","ts","tsa","tsac"]
   U                - upend (reverse each)              ["t","st","ast","cast"] (suffixes)
    Ụ               - sort indexes by value             [3,4,2,1] (lexicographical order)
     Ụ              - sort indexes by value             [4,3,1,2] (order of that)
      I             - incremental differences           [-1,-2,1] (change)
       Ṡ            - sign                              [-1,-1,1] (comparisons)
        µ           - monadic chain separation, call that x
         I          - incremental differences           [0,2] (only (-1,1) produce 2s)
          2         - literal 2                         2
           n        - not equal?                        [1,0] (indexes of * will be 0)
            ×       - multiply by x (vectorises)        [-1,0,1] (make indexes of *s 0)
              ØD    - decimal yield                     "0123456789"
             ị      - index into (1-indexed & modular)  ['8','9','0']
                Ṛ   - reverse                           ['0','9','8']
                 ;0 - concatenate a zero                ['0','9','8',0]
                    - implicit print                     0980
                    -                              i.e. "L*SL"

Benim için küçük bir açıklama eklemek ister misiniz?
Christoph

2
Tabii ki yapacağım - Önce olası golfleri düşünüyorum ...
Jonathan Allan


@LeakyNun Bunu nasıl çözdün ?! Orada bir hata kullanıyorum ben +dizeleri vectorise gibi görünüyor ama altta yatan sonuçlar aslında Jelly yinelenebilir değil ama dizeleri (!) (Örneğin deneyin +@/L€veya +@/L€€veya ...)
Jonathan Allan

@JonathanAllan evet, +gerçek dize üretir. Bu, belgelenmemiş bir özellik veya hata olarak adlandırdığınız özelliktir.
Leaky Nun

3

Python 3, 92 87 74 69 65 bayt

s=input()
c=1
while s:d=s<s[1:];print(d+(c<d),end='');s=s[1:];c=d

0İçin L, 1için Sve 2için kullanır *. Giriş dizesini tırnak işaretleri içine alın; Buna konvansiyon tarafından izin verildiğini düşünüyorum.

Çevrimiçi deneyin!

Örnek kullanım:

mmiissiissiippi
002100210021000

Leaky Nun sayesinde 5 bayt, ovs sayesinde 4 bayt tasarruf etti




3

JavaScript (ES6), 51 45 bayt

f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)

@Neil sayesinde 6 bayt kaydedildi.

Egzersize özyinelemeli bir çözüm.

f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)

console.log(f('mmiissiissiippi')); //LL*SLL*SLL*SLLL   002100210021000
console.log(f('hello world'));     //L*SSL*L*LLL       02110202000
console.log(f('Hello World'));     //SSSSL*SSLLL       11110211000
console.log(f('53Ab§%5qS'));       //L*SSL*SLL         021102100


6 bayt kaydet:f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)
Neil

Teşekkürler @Neil, orada bir yerlerde bir optimizasyon olması gerektiğini biliyordum .
Rick Hitchcock

2

JavaScript (ES6), 52 bayt

f=
s=>s.replace(/./g,_=>(c<(c=s<(s=s.slice(1))))+c,c=1)
<input oninput=o.textContent=f(this.value)><pre id=o>

Bağlantı noktası @ L3viathan'ın cevabı.


1
@ RickHitchcock Hata, bir şekilde liman c=1olarak başardım c=0...
Neil


1

Haskell , 77 75 bayt, doğrusal zaman

f(a:b:c)|let g"L"|a<b="SL";g"S"|a>b="L*";g d=d++d;d:e=f$b:c=g[d]++e
f _="L"

Çevrimiçi deneyin!

Nasıl çalışır

Bu, özyineleme kullanır ve dizenin başlangıcından bir kerede bir karakter çıkarır. (Haskell dize türü, tek bağlantılı bağlantılı bir karakter listesidir, bu nedenle bu adımların her biri sabit sürelidir.)

  • Bir dizi için abc bir ve b tekli karakterleri ve C bir (boş) dize,
    • f ( ABC ) = SL E , eğer f ( BC ) = L , e ve bir < b ;
    • f ( ABC ) = L * E , eğer f ( BC ) = S e ve bir > b ;
    • f ( ABC ) = ll , e , eğer f ( BC ) = L , e ve birB ;
    • f ( ABC ) = SS E , eğer f ( BC ) = S , e ve birb .
  • Tek karakterli bir dize a , f ( a ) = L için.

1
Lütfen bir açıklama yapabilir misiniz?
R. Kap

Bunun doğrusal bir zamanda çalıştığını doğrulayabilmem için lütfen bir açıklama girin.
Christoph

@Christoph Eklendi.
Anders Kaseorg

@AndersKaseorg eklediğiniz için teşekkürler! Ne yazık ki bu diğer Haskell cevabı ile karşılaştırıldığında oldukça ayrıntılı görünüyor. Bu, kullanılmadan daha da golf edilebilir S, L and *mi?
Christoph

1
@Christoph Açık olmak gerekirse [1,1,2,0,1,1,2,0,1,1,2,0,1,1,1], tek karakterlerin bir listesi değil, tek haneli sayıların bir listesidir. Benim durumumda, bir sayı listesi çıkarmanın bana hiç bayt kazandırmayacağını düşünüyorum.
Anders Kaseorg

1

Python 2 , 65 55 bayt

L3viathan'ın cevabını temel alan , aşağıdaki 012gibi yinelenen sürüm LS*:

def g(s,d=2):c=s<s[1:];return s and`c+(d<c)`+g(s[1:],c)

Çevrimiçi deneyin!

Python 3 , 65 59 bayt

Yinelemeli çözeltisi kullanılarak L, Sve *:

f=lambda s:s and('LS'[s<s[1:]]+f(s[1:])).replace('LS','L*')

Önden dize boyunca devam edecek ve tüm örneklerini arasında yerini LSileL*

Çevrimiçi deneyin!


1
blah if s else''s and blahaltı bayt kaydeder. Python 2'de, str(blah)`blah`ikinci çözüme üç bayt daha kaydeder.
Anders Kaseorg

1

PHP, 82 bayt, doğrusal zaman

for($a=$argn;a&$c=$a[$i-=1];$d=$c)$a[$i]=2+$t=$d<=>$c?:$t;echo strtr($a,[13=>12]);

Girişi sağdan sola doğru yürür ve her karakteri tür ile değiştirir.

$t=$d<=>$c?:$t

Akım ve önceki karaktere (-1 veya 1) verilen türü hesaplar. Eşitse tür değişmez.


Fikir için +1strtr
Jörg Hülsermann

1

PHP , 70 bayt

L = 1, S = 0, * = 2

Bunun yerine §+3 Bayt'lık son Testcase için Çokbaytlı Destek gereklidirmb_substrsubstr

for(;$s=&$argn;$s=$u)$r.=$l=($l&1)+(1&$l^($s>$u=substr($s,1)));echo$r;

Çevrimiçi deneyin!

PHP , 71 bayt

L = 1, S = 0, * = 2

for(;$s=&$argn;$s=$u)$r.=+($s>$u=substr($s,1));echo strtr($r,[10=>12]);

Çevrimiçi deneyin!

PHP , 74 bayt

for(;$s=&$argn;$s=$u)$r.=SL[$s>$u=substr($s,1)];echo strtr($r,[LS=>"L*"]);

Çevrimiçi deneyin!


$s=&$argnoldukça zeki ! Yine de daha iyi bir cevap var eminim;) Umarım birisi gelir :)
Christoph

@Christoph Bir şeyleri özlediğimi hissediyorum. Son LS * 'i bir
varibale'de

@Christoph böyle mi demek istiyorsun? Son test çantasının neden yanlış olduğunu gerçekten göremedim Çevrimiçi deneyin!
Jörg Hülsermann

@Christoph Tamam , giriş basit ascii aralığında değilse mb_substryerine kullanmam gereken son testcase için neden çalışmadığını gördüm substr. Son test çantasını desteklemek gerekli mi?
Jörg Hülsermann

1
@Christoph Teşekkür ederim Bu durumda§
Jörg Hülsermann
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.