Düşük yük sayısının en kısa gösterimi


13

Lezzet metni

Yığın tabanlı esolang Underload fonksiyonel programlamaya bazı ilginç bağları var. Bunlardan biri, sayısal veri türünün işlenmesidir - lambda hesabı gibi, N sayısını doğal olarak gerçekleştiren bir işlevle doğal N sayısını temsil edersiniz.

İşleri kolaylaştırmak için, yalnızca aşağıdaki Düşük Yük komutları alt kümesini dikkate alacağız:

  • : - Bu komut, yığındaki en üst öğeyi çoğaltır.
  • * - Bu komut, yığındaki ilk iki öğeyi tek bir öğede birleştirir.

Bir Düşük Yük rakamını N dizesi olarak tanımlarız :ve *yürütüldüğünde yığındaki en üst öğeyi tüketir ve bu öğenin birlikte birleştirilmiş N kopyalarını üretiriz. Bazı örnekler:

  • 0, -1, 1/2, Under gibi Düşük yük sayıları yoktur.
  • Boş dize Underload rakamı 1'dir, çünkü yığına dokunulmaz.
  • :*Düşük öğeyi 2 olarak gösterir, çünkü üst öğeyi çoğaltır ve sonra bu iki kopyayı tek bir öğede birleştirir: (A):*= (A)(A)*= (AA).
  • ::**Düşük yük rakamı 3: (A)::**= (A)(A):**= (A)(AA)*= (AAA).
  • :::*** Düşük yük rakamı 4'tür.
  • :*:*ayrıca Düşük yük rakamı 4: (A):*:*= (AA):*= (AA)(AA)*= (AAAA).

Genel olarak, M ve N Düşük yük sayıları ise Mve varsa N, o zaman :N*N + 1 MNrakamı ve M × N rakamı olduğunu göreceksiniz .

Meydan okuma

Göreviniz, en kısa programı (STDIN'de girdi alarak) veya işlevi (bağımsız değişken üzerinden girdi alarak) , Dize olarak girdisi için Düşük yük rakamının en kısa gösterimini üreten bir işlev yazmaktır . Yani, giriş pozitif bir doğal sayı N> 1 ise, karakterlerdeki uzunluğu diğer Düşük yük sayılarının N değerinden küçük veya ona eşit olan bir Düşük Yük rakamı N üretmelisiniz.

Örnek giriş ve çıkışlar: ("Giriş - OUTPUT.")

  • 1 - .
  • 2 - :*.
  • 5 - ::*:**(2 × 2 + 1).
  • 7 - ::*::***(2 × 3 + 1) veya :::**:**(3 × 2 + 1).
  • 33 - ::*:*:*:*:**(2 × 2 × 2 × 2 × 2 + 1).
  • 49 - ::*:*:*:*::***(16 × 3 + 1, uzunluk 14) ancak değil ::*::***::*::***(7 × 7, uzunluk 16).

Giriş pozitif bir doğal sayı değilse, bir hata döndürmekte, tanımlanmamış davranışlar üretmekte ve hatta sonlanamamakta serbestsiniz. Gönderinizin cevabı bulma yönteminin açıklaması takdir edilmektedir.

Standart boşluk deliği kısıtlamaları geçerlidir: ekstra giriş yok, web isteği yok, çıkış / dönüş değeri tam olarak cevap olmalı ve sonsuz bir rastgele akış :ve *vb olmamalıdır .


@Geobits Yürütme zamanı hakkında hiçbir şey söylemedim, sonuçta doğru cevabı vereceğini kanıtlayabildiğin sürece, iyisin.
algorithmmshark

2
Bu problem ekleme zincirleri ile ilgilidir; özel olarak ise, giriş için doğru cevabın uzunluğu xolan 2*A117498(x)burada A117498 bir ekleme zinciri bulmak için ikili ve faktör yöntemlerin en uygun kombinasyonunu verir.
Peter Taylor

Yanıtlar:


4

GolfScript ( 61 60 55 54 53 karakter)

~:X'']({:A{.'.+'\*A{2$+}%~}%}*{,}${1\~X=}?{44/'*:'=}%

Bu, önceki sürümümden daha az zor ve biraz farklı bir yaklaşım gerektiriyor, ancak yine de kaba kuvvet. Bunun ':'X*'*'X*+aday bir çözüm olduğunu biliyoruz , bu yüzden bu kadar iyi dengelenmiş tüm dizeler üretir ve doğru olanı değerlendiren en kısa olanı alırsak, bir tane bulacağımızdan emin olabiliriz.

# Evaluate input and store the target number in X
~:X
# Seed the generator with the empty string
'']
# X times...
({
    # Store the array of strings so far into A
    :A
    # Generate A' by mapping each element
    {
        # Dup: this leaves an untouched copy of the current string
        .
        # Wrap the duplicate in .+
        '.+'\*
        # For each element in A, generate that element suffixed with the current string
        A{2$+}%~
    }%
}*
# Order by length
{,}$
# Find the first element which evaluates to X
{1\~X=}?
# tr .+ :*
{44/'*:'=}%

Çözümünden bir çift 1 karakterlik tweak çaldığım Howard sayesinde.


Haha, 3 girişinin web yorumlayıcısında yürütülmesi üç saniyeden uzun sürüyor. En iyi golf.
algorithmmshark

@algorithmshark, veri tekilleştirme noktasıyla biraz hızlandırabilirsiniz. Takın .&yani arasındaki (sadece iç döngü sonra ~}%ve }*.
Peter Taylor

4

GolfScript ( 54 53 karakter)

Bu, Howard'ın ruhunda olan bir yaklaşımdır (doğru değeri değerlendirenleri bulmak için aday dizeler yoluyla kaba kuvvet yerine doğru değeri değerlendiren ve en kısa olan dizeleri oluşturma), ama bence yeterince farklı ayrı bir cevaba aittir.

~.''':*':s@,{):x,2>{:^~$x^/~$+{s\*}x^%*}%{,}$0=}/]((=

Çevrimiçi demo kullanılamıyor çünkü yorumlayıcının buggy sürümünü çalıştırıyor.

# Let <N> denote the string which evaluates to N
# We want to enter the main loop with three values on the stack: <0> <1> <2>
# However, we'll never use <0>, so we can actually replace that with any value at all.
# Getting the input from underneath 3 items would normally use two stack manipulations.
# Trick: let's use the input value for <0>! (This gives a further bonus later).
# NB We store the value of <2> in the variable s
~.''':*':s@
# for x=1 to input_value ...
,{):x
    # for ^=2 to x-1 ...
    ,2>{:^
        # Use negative stack offsets to index the stack from the start
        # I.e. -1$ gets the first item on the stack, which is <0>
        # -2$ gets the second item on the stack, which is <1>
        # In general, val~$ gets <val>
        ~$x^/~$+
        # We have the string <^><x / ^> on the stack.
        # Increment it (x % ^) times to get a candidate <x>.
        {s\*}x^%*
    }%
    # Select a shortest string.
    {,}$0=
}/
# Group the stack into one array and select the appropriate offset,
# reusing that hacky <0> substitute for the offset.
]((=

Değiştirerek birini tıraş mümkün olacağını 3+ile )(gerçeğini istismar []0=o olmasaydı yığın yaprak şey) []2>bir hata açar.
Peter Taylor

[]2>[]hatasız sonuç verir .
Howard

@Howard, ah, golfscript.apphb.com eski bir sürümünü çalıştırıyor olmalıdır . Ama yanlış olduğum ortaya çıkıyor, çünkü bu değiştirme giriş için yanlış çıktı almayı sağlıyor '1'.
Peter Taylor

Hangi ((=yerine ile düzeltebilirsiniz -1=.
Howard

Ve golfscript.apphb.com gerçekten eski bir sürümü çalıştırıyor, iç içe döngüler örneği çalışmıyor.
Howard

4

Python 2.7 - 87 84 92

u=lambda n:n>1and min([u(i)+u(n/i)for i in range(2,n)if n%i<1]+[':'+u(n-1)+'*'],key=len)or''

Açıklama:
Bu oldukça basit bir çözümdür. N'nin olası tüm temsillerini iki sayının çarpımı veya as olarak tekrar tekrar test eder :(n-1)*ve sonra minimum uzunluk çözümünü bulur. yineleme sınırlı derinliğe sahip olması için n (2, n) aralığı gereklidir ve n <2 temel durumu verir.

Notlar:
i ve n / i, n'nin iki faktörüdür. ... ve ... veya ... yerine ... eğer ... başka ... işe yaramıyor çünkü '' yanlış olarak değerlendiriliyor. dak dizeleri en kısa dizelerden birini verir. Python 2.7, // yerine / kullanarak 1 karakter kaydeder.

Düzenleme: Temel durumu ifadenin arkasına taşıyarak, ... ve ... veya ... kullanmamı ve birkaç boşluk tıraş etmemi sağladı.

Test senaryoları:

u(1)
''
u(5)
'::*:**'
u(49)
'::*:*:*:*::***'

1
" Dizeleri dk kısa dizelerinden birini verir " İsteğe bağlı bir argüman temin sürece doğru değildir key=len. Sözlükbilimsel olarak en erken dizeyi verir. ( Örnek ). Yana '*' < ':'bu yollarla size 2'nin katlarını içeren çözümlere doğru bir önyargı var, ama onlar her zaman en kısa olduğu?
Peter Taylor

1
Cevap: aslında önyargı daha karmaşıktır, ancak her zaman doğru cevabı vermez. En küçük karşıt örnek, u(33)sözlükbilimsel olarak sıralama 14 karakterlik, ::**::*::*:***ancak uzunluk değerlerine göre sıralama 12 karakterlik değer verir::*:*:*:*:**
Peter Taylor

1
Python string karşılaştırmaları hakkında bunu hiç bilmiyordum. Cevabımı güncelledim.
isaacg

3

GolfScript, 63 58 56 karakter

~n./\{:v~[':*'1$*v,,2>{v,\%!},{.v=v,@/v=+}/]{,}$0=]}*-2=

Kod STDIN üzerine giriş alır ve sonucu yazdırır.

Örnekler:

> 49
:::**:*:*:*:**

> 1234
::::*:*:*:**:*:*:**::**::***

Kendi vakalarınızı çevrimiçi olarak test edebilirsiniz .


Vay canına, faktoring temelli bir yaklaşımın kaba kuvvet yaklaşımından biraz daha uzun olacağını düşündüm.
Peter Taylor

@PeterTaylor Ben de öyle düşündüm ama durum böyle değildi. Dahası, kaba kuvvet çözümüm sizinkinden biraz daha uzundu ;-)
Howard

Her bölümün ne yaptığını açıklar mısın? Sadece bitene kadar takip edebilirim :x(=. Ayrıca, makul bir sürede 49'u çalıştırabildiği için +1.
algorithmmshark

@algorithmshark Hala çözüm üzerinde çalışıyorum, bu yüzden hala çok değişebilir (tıpkı yaptığı gibi). Temel olarak, bölüm x,2>{x\%!},tüm gerçek bölenleri verir x, {.v=x@/v=+}/sonra tüm bölenlere dve x/dtüm bölenlere yönelik çözümleri birleştirir d. {,}$uzunluklarına göre sıralar ve 0=en kısa olanını alır (artı ilk :(x-1)*durum).
Howard

2

Brachylog 2 , 30 (belki sonunda 26) bayt, dil postdates meydan okuma

Geçerli Brachylog 2 uygulamasıyla çalışan bir işlev şunlardır (ve geçerli uygulamanın dize işleme ile ilgili bazı sorunları olduğu için bir karakter kodları listesi döndürür):

∧.l∧?{ḋp~c×ᵐ{-₁↰₁:[42,58]c↻}ᵐc}

Çevrimiçi deneyin!

Dil hala çok yeni. İşte programın belirtime göre çalışması gereken 26 bitlik bir sürümü, ancak bazı eklenmemiş özellikleri kullanan ve bu nedenle henüz geçerli değil, ancak gelecekte de olacak (daha da az verimli):

{ḋp~c×ᵐ{-₁↰₁:"*:"c↻}ᵐc}ᶠlᵒh

açıklama

∧.l∧?{ḋp~c×ᵐ{-₁↰₁:[42,58]c↻}ᵐc}
∧.l∧?                            Evaluation hint: try shortest outputs first
     {                        }  Define an inner function
      ḋ                          Prime factor decomposition of the input
       p                         Find a permutation
        ~c                       Find an inverse concatenation (i.e. partition)
          ×ᵐ                     Take the product of each set inside the partition
      ḋp~c×ᵐ                     Find a decomposition into factors ≥ 2
            {              }ᵐ    For each of those factors:
             -₁                  Decrement it
               ↰₁                Call the inner function recursively
                 :[42,58]c       Append "*:" (as character codes)
                          ↻      Move the last element to the start
                             c   Append the results together

Temel fikir oldukça basittir: sayıyı (1 veya daha fazla) faktöre (mutlaka asal faktörler değil, 1 faktörüne izin verilmez) ayrıştırmak ve bunların her birini 1 + (özyinelemeden elde edilen bir gösterim) olarak ifade etmek arasında değişiyoruz. aramak). Bu, sayının tüm olası Düşük Yük temsillerini aramayı garanti eder (2'den fazla sayıyı çarparak "art arda iki kez" bir çarpım aşaması uygulayabiliriz ve bunları çarpma aşamasıyla ayırarak art arda iki kez bir artış aşaması uygulayabiliriz. birlikte sadece bir sayı). Açık bir temel duruma ihtiyacımız yoktur, çünkü 1'in asal faktörlere ayrıştırılması bize boş bir liste verir ve böylece sıfır sayıları bir araya getiren bir çarpma aşamasıyla inşa ederiz.

Program oldukça verimsiz, çünkü verdiğim değerlendirme emri ipucu (nihai çıktının büyüklüğü açısından en kısatan en uzununa cevaplar üretiyor) ve sorunun "en kısa" kısmını çözerken, aslında programı hızlı bir şekilde tamamlamak (çok daha faydalı bir ipucu "her özyinelemeli aşamada yalnızca en kısa cevabı üretmek" olacaktır, ancak bu daha fazla bayt alır ...). Ek olarak, ḋp~c×ᵐher biri birkaç kez çarpımsal bölümler oluşturabilir, bu da programın çok fazla iş yapmasını sağlar.


0

J - 81 karakter

Gelecek kuşak için bu, J'de yapabileceğim en iyisiydi.

_2{::(0&(][,0{<@;"1@({~#(#~]-:"1<.)@(],.%)2}.i.@#)(/:#&>)@,':'<@,'*',~>@{:),~)&a:

0 (hiç kullanılmamış) ve 1'i temsil eden iki boş dizeyle (bu ,~ve a:) başlayan bir sonuç listesi oluştururuz ve sonra bir &sonraki sayının en kısa temsilini ekleyen bir fiil (kancaların, trenlerin ve sinsi kullanımı) tekrarlar .

Yinelediğimiz fiil, listenin uzunluğunu, üzerinde çalıştığımız numaranın bir göstergesi olarak kullanır. İlk olarak, bu sayıyı faktör çiftleri ( #(#~]-:"1<.)@(],.%)2}.i.@#) olarak çarparız ve her çifti diziden ( {~) çekerek alırız . Bu çiftlerin her birini (sayı asalsa 0 olabilir) tek dizgiye ( <@;"1) çeviririz .

Sonra o listeye göre parantez önceki sonuca girişini eklemek :ve *sıralama ve uzunluğuyla bu liste ( (/:#&>)). Son olarak, bu listeden ( 0{) ilk sonucu alırız ve bunu temel dizinin ( [,) sonuna ekleriz . Döngü yinelendiğinde, 0'dan başlayarak girişten daha uzun bir 2 listemiz vardır. Bu nedenle, geri dönmemiz gereken sondan-son dizeye ( _2{::).

   un =: _2{::(0&(][,0{<@;"1@({~#(#~]-:"1<.)@(],.%)2}.i.@#)(/:#&>)@,':'<@,'*',~>@{:),~)&a:
   un 49
::*:*:*:*::***
   un 1234
:*::*:*:*::*::***::*::*:****
   un 10010
:*::*:*::***::*:*:*:*:*:*:*::***
   2 * (1 + 3 * 2^2) * (1 + 3 * 2^7)
10010
   6!:2 'un 10010'   NB. time in seconds
19.5539

0

Jelly , 33 bayt, dil postdates zorluğu

ÆḌḊµ⁹÷Ñ;Ñð€
’ß”:;;”*W;ÇLÞḢµ“”>1$?

Çevrimiçi deneyin!

Basit bir kaba kuvvet çözümü.

açıklama

Ana program

’ß”:;;”*W;ÇLÞḢµ“”>1$?
              µ  >1$?  If input is greater than 1, then:
’ß                       Run recursively on the input - 1
  ”:;                    Prepend a colon
     ;”*                 Append an asterisk
        W;               Cons to:
          Ç                the result of the helper, on {the original input}
           LÞ            Sort by length
             Ḣ           Take the first (i.e. shortest) result
               “”      Otherwise, return an empty string

Ana program, değeri çarpma yoluyla üretmek için tüm olası yolları numaralandırmak için yardımcı işlevini kullanır, ardından değeri ekleyerek üretmeye çalışır ve en kısa olasılığı döndürür. Ayrıca temel kasayı (bir girişi 1) ele alır.

Yardımcı işlevi

ÆḌḊµ⁹÷Ñ;Ñð€
ÆḌ µ     ð€            For all proper factors of the input
  Ḋ                    except the first (i.e. 1):
    ⁹÷                   Divide it into the input;
      Ñ                  Run the main program on it;
       ;                 Append the result of:
        Ñ                  the main program run on {the factor}

Yardımcı işlev, girdiyi iki sayının çarpımı olarak ifade etmek için tüm olası yöntemleri dener ve en kısa gösterimlerine ulaşmak için ana programı karşılıklı olarak özyinelemeli olarak çağırır.


0

GNU Prolog, 96 bayt

v(N)-->{N#=1};{N#=A*B,A#<B,B#<N},v(A),v(B);{N#=M+1},":",v(M),"*".
s(N,S):-length(S,_),v(N,S,[]).

İlk satır, Düşük Yük değerlendirmesini uygulayan ve ters yönde çalışan bir gramerdir (aslında, A#<Bkısıtlama nedeniyle ileri yönde pek işe yaramaz ; bunu A#<Nher iki yönde de çalışan daha yavaş bir program olarak değiştirin ). İkinci satır, sgirdi olarak verilen sayıya göre değerlendirilebilecek en kısa dizeyi bulan işlev benzeri yüklemi (bu programa bir çözüm olarak uygulanan işlevdir) tanımlar (bu nispeten basit bir görev için sinir bozucu bir şekilde ayrıntılıdır, ancak bu sizin için Prolog…).

Program, şartnamenin bir dilbilgisine ve daha sonra Prolog sözdizimine doğrudan bir çevirisi olduğu göz önüne alındığında, oldukça açıklayıcı olmalıdır; ifadesinin tanımı, boş bir dizede 1 volduğunu Nya Nda A× B( Adaha azdan Baz N) olduğunu ve dizenin v(A)ve v(B), ya Nda M+ 1'in :birleşimidir ve dize ile v(M)birleştirilir *. İkinci satır biraz daha incedir;length(S,_) "S'nin biraz uzunluğu var" anlamına gelir, ancak bunu satırdaki ilk şey olarak belirtmek, Prolog uygulamasına önce en kısa uzunlukları kontrol etmesi gerektiğini gösteren bir ipucu görevi görür (yani bir dönüş değeri için mümkün olan en kısa uzunluğu alacağız) .

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.