Bir dizinin kısaltması


26

Hedef:

Bir dizge dizisi verildiğinde, her dizenin kısaltılmış versiyonlarını oluşturun.

Şartname:

Bu zorluk için, bir kısaltma bir dizenin ilk N karakteridir. Dize için abc: a, abve abctüm geçerli kısaltmalar iken bcve acdeğillerdir.

Bir dizi dizi göz önüne alındığında, girdi ve herhangi bir kısaltma verildiğinde, kısaltmanın hangi öğeden bahsettiğini belirlemek için en kısa kısaltma kümesini bulmak istiyoruz.

Örnek:

Giriş: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

İlki ile başlayan iplerden geçiyoruz.

  • Pazartesi sadece bir öğe dizesidir M, bu yüzden mümkün olan en kısa kısaltmadır M.

  • Salı ile başlar T, ancak Perşembe de öyle. Bu, ipi denediğimiz anlamına gelir TU. Başka hiçbir dize buna başlamadığından, kullanırız TU.

  • Çarşamba W, perşembe Thve cuma F.

Daha fazla örnek:

Input: "one,two,three,four,five,six,seven"
Output: "o,tw,th,fo,fi,si,se"

Input: "red,orange,yellow,green,blue,purple"
Output: "r,o,y,g,b,p"

Input: "a,ab,abc"
Output: Not valid! No abbreviation for `a` that doesn't apply to the other items.

Notlar:

  • Herhangi bir makul şekilde giriş ve çıkış yaparsınız.

  • Girişin her zaman geçerli bir dize dizisi olacağını varsayabilirsiniz.

  • Son test durumundan farklı olarak her zaman bir çözüm olacağını varsayabilirsiniz.

  • Dizeler yalnızca yazdırılabilir ASCII'den (veya kodlamanızdaki yazdırılabilir karakterlerden) oluşur

  • Bu kod golf, yani en az bayt kazanıyor!


İlgili: 1 , 2 , 3
Sp3000 18:17


2
Bunların hiçbirinin kopyası olduğunu sanmıyorum (hepsi birbirine benzese de). Aslında, bunun muhtemelen dört kişi arasındaki en iyi zorluk olduğunu düşünüyorum; diğerleri ise onları gereksiz yere karmaşık kılan değişkenlere sahiptir.

2
Dava önemli mi? Özellikle, hafta içi örneğiniz USalı için bir büyük harf h, Perşembe için küçük bir harf kullanır.
Brian J

1
@Mego Bir denetleyici kopya olmadıkça işaretlemediği sürece yazımı düzenlemeyin
Julian Lachniet

Yanıtlar:


10

Retina , 29 bayt

!ms`^(.+?)(?!.+^\1)(?<!^\1.+)

Giriş ve çıkış dizgelerin satır beslemeli ayrılmış listeleridir.

Çevrimiçi deneyin! (Kolaylık sağlamak için virgülle ayrılmış test paketi.)

açıklama

Bu sadece tüm önekleri tek bir regex ile eşleştirir ve yazdırır ( !). mve maç satırının başlangıcını syapmak ^ve .satır akışlarını eşleştirmek için kullanılan normal regex değiştiricileridir .

^(.+?)      # Match the shortest possible prefix of a line and capture
            # it in group 1.
(?!.+^\1)   # Make sure that this prefix does not show up in a line after
            # the current one.
(?<!^\1.+)  # Make sure that this prefix does not show up in a line before
            # the current one.

10

Python 2 , 87 86 bayt

lambda a:[b[:min(i for i in range(len(b))if sum(s[:i]==b[:i]for s in a)<2)]for b in a]

Çevrimiçi deneyin!


lambda a:[[b[:i]for i in range(len(b))if sum(s[:i]==b[:i]for s in a)<2][0]for b in a]85 bayt için
Curtis Bechtel

değiştirilmesi len(b)ile 4**8dizeleri 65536 karakterden daha artık olacağını varsayarak, 2 daha bayt kaydeder
Curtis Bechtel

8

JavaScript (ES6), 81 78 74 70 bayt

Dizeleri bir dizi olarak girdi alır.

a=>a.map(s=>[...s].reduce((y,c)=>a.some(x=>x!=s&!x.indexOf(y))?y+c:y))

Biçimlendi ve yorumlandı

a =>                          // given an array of strings 'a'
  a.map(s =>                  // for each string 's' in 'a':
    [...s].reduce((y, c) =>   //   starting with 'y' = first character of 's',
                              //   for each subsequent character 'c' of 's':
      a.some(x =>             //     if we find a string 'x' in 'a' such that:
        x != s &              //       - 'x' is different from 's'
        !x.indexOf(y)         //       - and 'y' appears at the beginning of 'x'
      ) ?                     //     then:
        y + c                 //       append 'c' to 'y'
      :                       //     else:
        y                     //       keep 'y' unchanged
    )                         //   end of reduce(): returns the correct prefix
  )                           // end of map()

Test durumları


1
70 de, ancak kesinlikle başka: codegolf.stackexchange.com/a/113270/32091
Qwertiy

İçin +1 reduce.
Neil

6

Jöle , 14 bayt

;\w@þ=1Si1⁸ḣð€

Çevrimiçi deneyin!

Nasıl çalışır

;\w@þ=1Si1⁸ḣð€  Monadic link. Argument: A (string array)

            ð   Collect all links to the left into a chain (arity unknown) and
                begin a dyadic chain.
             €  Map the previous chain over A. The current chain is dyadic and the
                mapped one inherits its arity. Thus, the right will be A for all
                invocations, while the left argument will iterate over A.
                For each string s in A, the following happens.
;\                Cumulative reduce by concatenation; yield all prefixes of s.
  w@þ             Window index swapped table; for each string t in A and each
                  prefix p of s, find the index of the substring t in p.
                  The first index is 1; 0 means not found.
     =1           Compare the indices with 1, returning 1 iff t begins with p.
       S          Sum the Booleans across columns, counting the number of strings
                  in A that begin with a given prefix.
        i1        Find the first index of 1, the shortest prefix that is unique
                  across all strings in A.
          ⁸       Head; truncate s to the computed length.

6

Haskell , 48 bayt

[_]#x=""
a#(c:y)=c:[z|d:z<-a,c==d]#y
f=map=<<(#)

Çevrimiçi deneyin!

  • fasıl fonksiyon, Strings listesini alarak ve a döndürür String. Tanımı için monadik bir kestirme f a=map (a#) a.
  • a#xdizge'nin bakar xve liste ave çalışır en kısa öneki bulmak için xo eşsizdir a. Eğer atek bir öğeye sahiptir, sadece boş bir dize kullanın. Eğer azaten tek unsur değil, ilk karakteri kesmek xfiltresi ve unsurlarını doğrayın aaynı karakterle başlayan ve ardından Recurse.

4

Mathematica, 64 bayt

#&@@@StringCases[#,Shortest@x__/;Tr@Boole@StringStartsQ[#,x]<2]&

3

Jöle , 14 12 bayt

ḣ€JṙLḶ$ḟ/€Ḣ€

Çevrimiçi deneyin!

Nasıl çalışır

ḣ€JṙLḶ$ḟ/€Ḣ€  Main link. Argument: A (string array)

  J           Yield the 1-based indices of A, i.e., [1, ..., len(A)].
ḣ€            Head each; for each string s in A, take the first 1, ..., and len(A) 
              characters. This builds the 2D array of prefixes of all strings in A.
    LḶ$       Length-unlength; yield [0, ..., len(A)-1].
   ṙ          Rotate the 2D array 0, ..., and len(A)-1 units to the left.
       ḟ/€    Reduce filterfalse each; for each rotation, remove all prefixes from
              the first set that also occur in later sets.
          Ḣ€  Head each; for each rotation, keep only the shortest unique prefix.

Merak ediyorum, neden burada 2 cevabınız var? İkisini de seviyorum ama neden burada iki Jelly cevabınızın olduğunu merak ediyorum. :)
HyperNeutrino

Eğer benzer şekilde rekabetçi iki yaklaşıma sahipsem ancak yeterince farklı yaklaşımlara sahipsem, genellikle bunları ayrı cevaplar halinde gönderirim.
Dennis,

İyi bir nokta. Evet, sadece merak ediyordum. :) Bu iyi bir fikir; Genellikle birden fazla yaklaşıma sahip değilim: P
HyperNeutrino

2

C ++ 11 (MinGW), 198 bayt

#import<list>
#import<iostream>
f(std::list<std::string>l){int i,m;for(auto s:l){for(i=0,m=1;++i<s.length();)for(auto t:l)if(t!=s&&t.substr(0,i)==s.substr(0,i))m=i+1;std::cout<<s.substr(0,m)<<" ";}}

İle ara:

int main()
{
    f({"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"});
}

İşlevden voidönce tanımlayıcı eklemek , onu diğer derleyicilerde de derlemeli ve böylece uzunluğa 5 bayt eklemelidir.


O olmalı void f...aksi işi does't ... + 5 bayt maalesef. Bildiğim kadarıyla, C ++
Mr. Xcoder

Bunun yanı sıra, olağanüstü bir yaklaşım! C / C ++ 'da golf
oynamak

@ Mr.Xcoder Yine de kullandığım MinGW derleyicisini derliyor. Bu yüzden ya bir derleyici uzantısı ya da tanımsız bir davranış.
Steadybox

Ben derleyici uzantısı ile ilgili olduğunu düşünüyorum, GCC üzerinde işe yaramadı ...
Bay Xcoder

1
Kodun çalıştığı bir ortam olduğu sürece geçerlidir
undergroundmonorail

2

Javascript ES6, 70 karakter

s=>(s+'#'+s).replace(/(\w+?)(\w*)(?=(\W(?!\1(?!\2))\w+)+$)|#.+/g,"$1")

f=s=>(s+'#'+s).replace(/(\w+?)(\w*)(?=(\W(?!\1(?!\2))\w+)+$)|#.+/g,"$1")

console.log(f("one,two,three,four,five,six,seven")==="o,tw,th,fo,fi,si,se")
console.log(f("red,orange,yellow,green,blue,purple")==="r,o,y,g,b,p")
console.log(f("one,two,three,four,five,six,seven".split`,`)==="o,tw,th,fo,fi,si,se")
console.log(f("red,orange,yellow,green,blue,purple".split`,`)==="r,o,y,g,b,p")


2

PHP, 131 120 119 118 bayt

Jörg için teşekkürler preg_grep.

for(;a&$s=$argv[++$k];$i=+$t=!print"$t
")for(;a&$s[$i]&&1<count(preg_grep("(^".preg_quote($t.=$s[$i++]).")",$argv)););

komut satırı argümanlarından girdi alır; sonuçları her biri bir satır yazdırır. Çevrimiçi olarak
çalıştırın -nrveya deneyin .

  • giriş ile başlayan bir şey içeriyorsa başarısız olabilir -.
    +15 bayt düzeltmek için: ikinci değiştirin$argv ilearray_slice($argv,1) .
  • PHP 7.1'deki uyarıları verir; yerine a&sahip""<düzeltmek için (+1 byte) .
  • -12 bayt giriş hiçbir normal ifadedeki özel karakter içeriyorsa:
    Ekleme &($t.=$c)önce &&ve değiştirme ". preg_quote($t.=$c)."ile $t.

Yıkmak

for(;a&$s=$argv[++$k];      # loop $s through arguments
    $i=+$t=!                # 3. reset $i and $t to empty
    print"$t\n")            # 2. print abbreviation
    for(;a&($c=$s[$i++])    # 1. loop $c through characters
        &&1<count(              # 3. if count==1, break loop
            preg_grep("(^"      # 2. find matching arguments
                . preg_quote(
                $t.=$c          # 1. append $c to abbreviation
            ).")",$argv)
        );
    );

regex olmayan sürüm, 131 130 bayt

for($a=$argv;a&$s=$a[++$k];$i=+$t=!print"$t
")for($n=1;$n&&a&$c=$s[$i++];)for($n=$m=1,$t.=$c;a&$u=$a[$m++];)$n-=0===strpos($u,$t);

İlk ve son değiştirin a&ile ""<PHP 7.1 için düzeltme için (2 byte).

Yıkmak

for($a=$argv;a&$s=$a[++$k];     # loop through arguments
    $i=+$t=!print"$t\n")            # 2. print abbreviation, reset $i and $t to empty
    for($n=1;$n&&a&$c=$s[$i++];)    # 1. loop through characters while $n<>0
        for($n=$m=1,                    # reset $n and $m to 1
            $t.=$c;                     # append current character to prefix
            a&$u=$a[$m++];              # loop through arguments:
        )$n-=0===strpos($u,$t);         # -$n = number of matching strings -1

Tamamen ilginç olmayan not:
strstr($u,$t)==$uve 0===strpos($u,$t)aynı uzunlukta ve aynı sonuca sahip.


0x0ABunun yerine gerçek bir yeni satır karakteri ( ) kullanın, \nbir bayttan tasarruf ettirin;).
Karadelik

@ Blackhole Teşekkürler; Bu sefer bunu unuttum.
Titus

1

PHP, 127 Bayt

geçersiz dizilerle çalışmaz

<?foreach($a=$_GET as$k=>$v)for($i=0,$c=2,$s="";$c>1;$r[$k]=$s)$c=count(preg_grep("_^".($s.=$v[$i++])._,$a));echo join(",",$r);

PHP, 132 Bayt

<?foreach($a=$_GET as$v)for($i=0,$s="";a&$v[$i];)if(count(preg_grep("_^".($s.=$v[$i++])._,$a))==1){$r[]=$s;break;}echo join(",",$r);

Çevrimiçi sürüm

151 Bayt özel karakterleri destekler

<?foreach($a=$_GET as$v)for($i=0,$s="";a&$v[$i];)if(count(preg_grep("_^".preg_quote($s=substr($v,0,++$i),_)._,$a))==1){$r[]=$s;break;}echo join(",",$r);

PHP, 140 Bayt

<?foreach($a=$_GET as$k=>$v)for($i=0;a&$v[$i];)if(count(preg_grep("#^".($s=substr($v,0,++$i))."#",$a))==1){$r[]=$s;break;}echo join(",",$r);

Giriş, regex özel karakterleri içeriyorsa, bu başarısız olur. Olmazsa 131 yerine 113 bayt olur.
Titus

@Titus Bu durumda preg_quotedaha fazla 10 bayt yap
Jörg Hülsermann

Girdi içeriyorsa da başarısız olur 0. Ancak bir bayt ile kaydedebilirsiniz $i=+$s="".
Titus

ve count()-count()öğeleri kaldırabilirsiniz : girişin geçerli olduğu garantilidir (-21 bayt). Sanırım bunu 120 bayta indirebilir ve golf oynayabilirim. $_GETiyi bir fikirdi!
Titus

@Titus Yalnızca geçerli dizilere izin verildiğini anlamadım. Evet, dizenin sıfır içermesi halinde başarısız olur, ancak bu bir fikir
doğurdu

0

Clojure, 118 bayt

#(reduce(partial map(fn[a b](or a b)))(for[i(range 1e2)S[(for[c %](take i c))]](for[s S](if(=((frequencies S)s)1)s))))

Bu, en fazla önek üzerinde çalışır 1e2ancak aynı bayt sayısı kadar destekleyebilir 1e9. iöneklerin uzunluğunu döngüler, uzunluktaki Salt dizilerin dizisidir i. Sonuncusu , bir defadan fazla olan forbu alt dizelerin yerini alır nil. Azaltma her dize için ilk sıfır olmayan değeri tutar, çok kötü orbir işlev değildir, bu yüzden sarmam gerekti.

Bu aslında gibi karakter listelerinin listesini döndürür ((\M) (\T \u) (\W) (\T \h) (\F)), ancak kabul edilebilir olduğunu düşünüyorum. Clojure oldukça ayrıntılı dizeleri ile, ve subsatardı StringIndexOutOfBoundsExceptionaksinetake .

Tam örnekler:

(def f #(reduce(partial map(fn[a b](or a b)))(for[i(range 1e2)S[(for[c %](take i c))]](for[s S](if(=((frequencies S)s)1)s)))))

(f ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"])
(f (re-seq #"[^,]+" "one,two,three,four,five,six,seven"))
(f (re-seq #"[^,]+" "red,orange,yellow,green,blue,purple"))

0

SQL (PostgreSQL 9.4 lezzet), 219 bayt

Şimdi en uzun cevap için :) Bunun Java'yı bile yenebileceğini sanmıyorum. Bundan bir kaç tane daha tıraş olmaya çalışacağım. İç içe geçmiş sorgulardan birinden kurtulmak umuduyla, ancak şansımı sevmiyorum
Bu, üzerinde çalışılacak dizeleri içeren bir tablo olduğunu varsayar. Bu SQL olduğundan, geri dönüş sırasının tablo sırasının aynı olması ve bu durumda düşük olması garanti edilmez. Bu bir problemse silerim.

SELECT R FROM(SELECT*,RANK()OVER(PARTITION BY A ORDER BY C,N)Z FROM(SELECT*,SUM(1)OVER(PARTITION BY R)C FROM(SELECT*FROM A JOIN LATERAL(select left(A,n)R,N FROM generate_series(1,length(A))S(n))L ON 1=1)X)Y)Z WHERE Z=1

SQL Fiddle
Açıklaması

  SELECT *
  FROM A 
    JOIN LATERAL(SELECT LEFT(A,n)R,N 
    FROM generate_series(1,length(A))S(n))L ON 1=1

En içteki sorgu , dize için artan uzunluklara bölünen satırlar oluşturmak üzere generate_seriesbir LATERALbirleştirme kullanır ve böylece 'bir', 'o', 'açık', 'bir' olur. Ayrıca geri dönüşteki karakter sayısı da tutulur.

SELECT 
  *,
  SUM(1)OVER(PARTITION BY R)C
FROM ( ... )X

Daha sonra aynı sonucu alan kayıt sayısını ekledik. Örneğin, dördüncü ve beşinci “f” sayısı 2'dir, ancak “fo” ve “fi” nin her biri birdir. SQL'deki OVERifade oldukça güçlü olabilir. COUNT(*)her zamanki gibi olur, ama SUM(1)aynı sonucu verir.

SELECT 
  *,
  RANK()OVER(PARTITION BY A ORDER BY C,N)Z
FROM ( ... )Y

Sonra her giriş için sonuçları en az tekrar ve karaktere göre sıralıyoruz. ROW_NUMBERBurada da çalışacaktı, ama daha uzun.

SELECT R FROM ( ... )Z WHERE Z=1;

Sonunda her kelime için en düşük rütbe sayısını seçiyoruz.



0

APL (Dyalog) , 27 bayt

{⍵↑¨⍨1⍳⍨¨↓+/(↑,⍵)∘.(⊃⍷)⍵}

Çevrimiçi deneyin!

{ anonim bir işlev, burada ⍵ argümanı temsil eder ...

∘.( işlevin bulunduğu bir işlev tablosu

   ilk elemanı

   Boolean listesi "sol argüman burada sağ argümanla başlıyor?"

) doğru argümanlar nerede

 tartışmalar

( ve sol argüman

   oluşan satır içeren bir tablo

  ,/ önekleri

  ¨ her biri

   argümanlar

+/ toplamı göster (bu önekle kaç tane argümanın yaklaştığını sayar)

 tabloyu satır listesine böl

⍳⍨¨ her birinde, ilk konumunu bul

1 bir (yani sadece bir argüman taşıyan ilk önek)

↑¨⍨ Her konum için ilgili öğeden bu kadar karakter çeker.

 argüman

} adsız işlevin sonu


0

PowerShell, 151 139 bayt

$x,$w=@(),$args[0];$w|%{$k=$_;$a='';foreach($l in [char[]]$k){$a+=$l;if($a-notin$x-and!($w|?{$_-ne$k-and$_-like"$a*"})){$x+=$a;break;}}};$x

Bunu yapmanın daha iyi bir yolu varsa, ilgileniyorum. Gerçekleştirmek için foreach(a |%) bir kullanmak zorunda kaldıbreakEtiketlenmeden iç içe döngüde zorunda kaldı.

Düzenleme: AdmBorkBork gelen 2 golf


1
Doğrudan kodu geçmedim, ancak elbette bazı baytları kaydetmek yerine ve yerine kullanabilirsiniz -notin. -not$x.contains($a)!($w...-not($w...
AdmBorkBork, 21.07

0

APL, 26 bayt

{⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}

Açıklama:

  • ↓↑⍵: her dizgiyi doldur en uzun dizginin uzunluğuna uyacak şekilde kaydır
  • ∘.(... )⍨: her olası dizge çifti için paylaşılan öneki bulun:
    • : dizi eşitsizliği
    • : ve
    • =: madde bazında eşitlik
    • ∧\: and-scan (yalnızca önde gelen eşleşmeleri koru)
  • +/¨: tablodaki her vektörü toplayın, paylaşılan öneklerin uzunluğunu verin
  • ⌈/: her sütunda maksimum değeri bul
  • 1+: her bir dizgeyi benzersiz tutmak için gereken karakter miktarlarını vererek bir tane ekleyin
  • ⍵↑¨⍨: her dizgiden o kadar karakter al

Ölçek:

      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday'
┌─┬──┬─┬──┬─┐
│M│Tu│W│Th│F│
└─┴──┴─┴──┴─┘
      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'one' 'two' 'three' 'four' 'five' 'six' 'seven'
┌─┬──┬──┬──┬──┬──┬──┐
│o│tw│th│fo│fi│si│se│
└─┴──┴──┴──┴──┴──┴──┘
      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'red' 'orange' 'yellow' 'green' 'blue' 'purple'
┌─┬─┬─┬─┬─┬─┐
│r│o│y│g│b│p│
└─┴─┴─┴─┴─┴─┘

0

Q, 93 bayt

{n:1;{$[any e:(,/)1<{(+/)i like x}each i:z#'x;[z+:1;y:?[e;z#'x;i];.z.s[x;y;z]];y]}[x;n#'x;n]}

Özyinelemeyle çözüldü, girdi olarak dizeyi aldı, her öznitelikle her dizenin ilk n öğelerini alır. Bu öğelerden herhangi biri benzersiz değilse, ilk n + 1 öğeleriyle değiştirir.

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.