Uzunluğuna eşit ifade


14

Bir sayı verildiğinde, bu sayının uzunluğuna eşit kelimelerde bir ifade bulun.

Bu durumda, bir girişine 15, çıktısını olabilir sixteen minus oneon beş karakter vardır, (boşluk hariç). Birden fazla çözüm varsa, istediğinizi yazdırın. Hiçbiri yoksa yazdırınimpossible

Yalnızca operatörler plus, minus, times, ve divided by. Operatörler soldan sağa değerlendirilir.

1234 biçimini biçimlendirin one thousand two hundred thirty four. "Ve" işaretinin bulunmadığına ve tire veya virgül olmadığına dikkat edin.

Giriş ve çıkışta kullanılan tüm sayılar 10.000'den az pozitif tamsayı olmalıdır.

Giriş bir komut satırı argümanı olarak verilecektir. Standart çıktıya yazdırın.

Örnekler

1: impossible
4: four
7: impossible
13: eight plus five (you could also output "five plus eight")
18: one plus two times six (note that operators are evaluated from left to right)
25: one thousand divided by forty

4
negatif olmayan tamsayılar? So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.Sıfırı hariç tutmak isteyebilirsiniz. Sana bağlı.
Level River St

@steveverrill İyi bir nokta; Bunu "pozitif tamsayılar" olarak değiştirdim.
Ypnypn

4
sooo ... one hundred three times one times one times one times one times one times one times one times one times one times one times onegeçerli mi?
Qwix

@Qwix Evet; 104, 105, 106, 107, 108, 109, 110 veya 111 için işe yaramaz olmasına rağmen sıkıcı cevaplar kabul edilebilir.
Ypnypn

Yanıtlar:


1

Javascript, 434 karakter

function f(s){return s.replace(/[A-Z]/g,function(t){return{O:'one',T:'two',H:'three',F:'four',I:'five',S:'six',E:'seven',G:'eight',N:'nine',Z:'ten',P:' plus ',M:' minus ',U:' times ',X:'teen',A:'thir',B:'twenty'}[t]})}A='TPAX|GeenMT|EXUO|B FMS|F|GPSUT|ZPHPG|BPFMT|AXPFPS|BPGMF|EUOPGeen|NPT|B GMSPI|GPI|EPE'.split('|');O=26640;function S(n){return n<15&&!(O>>n&1)?'Invalid':f(A[v=n%15])+(new Array(~~(n/15)+(O>>v&1))).join(f('PSPN'))}

Genel ad alanında, Snegatif olmayan tamsayıları kabul eden ve gerekli dizeyi döndüren veya "Invalid"tamsayı belirtimler dahilinde gösterilemiyorsa bir işlev verir .

@Optokopper ile aynı yaklaşımı kullandığım ve "plus six plus nine"mümkün olan en kısa dolgu dizesi ile aynı gözlemi yaptığım ve 27'den büyük tüm sayıların pedin tekrarlanan kopyalarına birleştirilmesiyle ifade edilebileceği anlaşılıyor.

Bunu söyledikten sonra, kullandığımız temel dizelerin tabloları farklıdır ve çözümüm bit döndürmeye ve geri kalan operatöre ( %) dayanmaktadır . Ayrıca "multiplied by"olası bir işlemi de içerir . Ve doğal olarak, dizelerin nasıl inşa edildiğinin mekaniği, C ve Javascript arasındaki farklılık nedeniyle tamamen farklıdır.

Bu benim en iyi girişimim. ;)

Hangi sayıların elde edilebileceği tartışması @chiru'ya özel teşekkürler, meyvesiz aramanın önlenmesine yardımcı oldu.


22

JS, 1719/1694

teori

Maalesef, sağladığınız kural kümesi matematiksel açıdan akıllıca bir karar olmayabilir. Aslında, daha küçük bir kural alt kümesi kullanarak, verilen aralıktaki her sayı için bir çözüm bulabilirsiniz.

I = [1;  10000]

dışında

X = [1;  3] 8 [5;  10] ∪ {12}

bunun için bir çözüm yoktur.

İndirgenmiş kural seti

Aşağıdaki kural alt kümesini düşünün:

  • Yalnızca operatörlerini kullanın plus, minusve times.
  • Sen uygulamak gerekmez birden fazla kopyasını plusveya minusifadelerinizdeki.
  • Sen uygulamak gerekmez ne divisionde operator associativity(onların çözüm kümesi zaten birinci kuralının geçerli olduğu gibi).

Bunun çalışmasının nedeni, @Qwix ile daha önce tartıştığınız gibi sıkıcı cevaplara , yani normal ifadeyle biten ifadelere izin vermenizdir ( times one)+$. Buna izin vermek gerekirse, verilen aralıktaki her sayının bir çözümü olacaktır.

Yorumlarınızdan birinde cevap verdiğinizde,

@Qwix Evet; 104, 105, 106, 107, 108, 109, 110 veya 111 için işe yaramasa da sıkıcı cevaplar kabul edilebilir. -

kesinlikle haklıydınız: İfadenizi sayılardan başlayarak, yani bu sayılardan başlayarak oluşturmaya çalıştığınızda bu işe yaramaz one hundred four times one times one ….

Bununla birlikte, ifadeniz, değerlendirmesi verilen sayılardan birine eşit olan bir ifadeyle başlarsa, şansınız kalmaz. Örneğin, bunun 17 + 87gerçekten olduğunu unutmayın 104, böylece şöyle yazabiliriz 104:

104: seventeen plus eighty seven times one times one times one times one times one times one times one times one times one times one

Bu alt kümenin çalıştığını görmek için bu dosyayı farklı kaydedin num.jsve komut satırları için bir JavaScript motoru olan SpiderMonkey'in sisteminizde yüklü olduğundan emin olun.

Algoritma

  • KPozitif tamsayıların özelliğini Nharflere ve değerine sahip sayının durumu olarak tanımlayalım N.
  • Ayrıca F, bir ifadenin özelliğini 8k, k-evaluation ℕ ile değerlendirmesinden daha kısa sürelerdeki kelime dönüştürme durumu olarak tanımlayalım. F"doldurulabilir" anlamına gelir ve ifadenin kelime dönüşümünü uzunluk (8 " times one") ifadeleriyle doldurabilip dolduramayacağımızı açıklar, böylece elde edilen ifade özelliği alabilir N.

Daha sonra şu şekilde ilerleriz:

  • Giriş numarasını kelimelere dönüştürün.
  • Giriş numarasının özelliği olup olmadığını kontrol edin K.
    • Eğer öyleyse, kelimeleri döndür ( 4maalesef bu özelliğe sahip tek sayıdır).
    • Değilse, devam edin.
  • Girdi numarasıyla sonuçlanan tüm iki işlenen ifadeler (bu sırayla toplama, çıkarma ve çarpma) için değerlendirmelerinde özellik olup olmadığını kontrol edin K.
    • Varsa, kelimeleri iade edin.
    • Değilse, iki işlenen ifadenin özelliği olup olmadığını kontrol edin N.
      • Varsa, ifadeyi doldurun " times one"ve elde edilen ifadenin değerlendirmesinin bir özelliği olup olmadığını kontrol edin K.
        • Varsa, kelimeleri iade edin
        • Değilse, devam edin
      • Değilse, devam edin
  • Git bir kahve iç

Uygulama

num.js (SpiderMonkey / komut satırları için)

function X(e,t){return e+": "+t}function P(e){var n,t;for(n=1;.5*e+(e%2===0?1:0)>n;++n){if(t=C.s(n)+" plus "+C.s(e-n),t.replace(/\s/g,"").length===e)return t;if(F(e,t)&&e>t.length)return G(e,t)}return!1}function M(e){var t,n;for(t=L;t>1;--t){if(0>t-e)return!1;if(n=C.s(t)+" minus "+C.s(t-e),n.replace(/\s/g,"").length===e)return n;if(F(e,n)&&e>n.length)return G(e,n)}return!1}function F(e,t){return(e-t.replace(/\s/g,"").length)%8===0}function G(r,t){var e,i=(r-t.replace(/\s/g,"").length)/8,n="";for(e=0;i>e;++e)n+=" times one";return t+n}function T(e){var t,n,r;if(F(e,C.s(e)))return G(e,C.s(e));for(t=1,n=1;t<Math.floor(Math.sqrt(e));++t){for(;e>tn;)++n;if(tn===e&&(r=C.s(t)+" times "+C.s(n),r.replace(/\s/g,"").length===e))return r}return!1}function Y(e){var n,r,t;return e===C.s(e).length?X(e,C.s(e)):(n=P(e))?X(e,n):(r=M(e))?X(e,r):(t=T(e),t?X(e,t):X(e,"impossible"))}var L=1e4,C=new function(){return this.o=["","one","two","three","four","five","six","seven","eight","nine"],this.t=["","","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"],this.T=["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],this.s=function(e){return e?this.m(e):"zero"},this.m=function(e){return e>=1e6?this.m(Math.floor(e/1e6))+" million"+(e%1e6!==0?" "+this.Z(e%1e6):""):this.Z(e)},this.Z=function(e){return e>=1e3?this.h(Math.floor(e/1e3))+" thousand"+(e%1e3!==0?" "+this.h(e%1e3):""):this.h(e)},this.h=function(e){return e>99?this.o[Math.floor(e/100)]+" hundred"+(e%100!==0?" "+this.U(e%100):""):this.U(e)},this.U=function(e){return 10>e?this.o[e]:e>=10&&20>e?this.T[e-10]:this.t[Math.floor(e/10)]+(e%10!==0?" "+this.o[e%10]:"")},this};print(Y(0|arguments[0]))

num.js (tarayıcılar için)

Yukarıdaki kod, verilen komut dosyasından güzel bir komut oluşturmak için komut satırı bağımsız değişkenlerini alan son komutu nedeniyle tarayıcılar için çalışamaz.

JavaScript kodunu doğrudan tarayıcınızdan çalıştırmak için yukarıdaki kodun bu parçasını seçin:

function X(e,t){return e+": "+t}function P(e){var n,t;for(n=1;.5*e+(e%2===0?1:0)>n;++n){if(t=C.s(n)+" plus "+C.s(e-n),t.replace(/\s/g,"").length===e)return t;if(F(e,t)&&e>t.length)return G(e,t)}return!1}function M(e){var t,n;for(t=L;t>1;--t){if(0>t-e)return!1;if(n=C.s(t)+" minus "+C.s(t-e),n.replace(/\s/g,"").length===e)return n;if(F(e,n)&&e>n.length)return G(e,n)}return!1}function F(e,t){return(e-t.replace(/\s/g,"").length)%8===0}function G(r,t){var e,i=(r-t.replace(/\s/g,"").length)/8,n="";for(e=0;i>e;++e)n+=" times one";return t+n}function T(e){var t,n,r;if(F(e,C.s(e)))return G(e,C.s(e));for(t=1,n=1;t<Math.floor(Math.sqrt(e));++t){for(;e>tn;)++n;if(tn===e&&(r=C.s(t)+" times "+C.s(n),r.replace(/\s/g,"").length===e))return r}return!1}function Y(e){var n,r,t;return e===C.s(e).length?X(e,C.s(e)):(n=P(e))?X(e,n):(r=M(e))?X(e,r):(t=T(e),t?X(e,t):X(e,"impossible"))}var L=1e4,C=new function(){return this.o=["","one","two","three","four","five","six","seven","eight","nine"],this.t=["","","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"],this.T=["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],this.s=function(e){return e?this.m(e):"zero"},this.m=function(e){return e>=1e6?this.m(Math.floor(e/1e6))+" million"+(e%1e6!==0?" "+this.Z(e%1e6):""):this.Z(e)},this.Z=function(e){return e>=1e3?this.h(Math.floor(e/1e3))+" thousand"+(e%1e3!==0?" "+this.h(e%1e3):""):this.h(e)},this.h=function(e){return e>99?this.o[Math.floor(e/100)]+" hundred"+(e%100!==0?" "+this.U(e%100):""):this.U(e)},this.U=function(e){return 10>e?this.o[e]:e>=10&&20>e?this.T[e-10]:this.t[Math.floor(e/10)]+(e%10!==0?" "+this.o[e%10]:"")},this}

Şimdi tarayıcınızın JavaScript konsoluna yapıştırın, böylece aynı sonuçları tarayıcınızdan aşağıdakilerle üretebilirsiniz:

Y(1234);

Örnekler (komut satırı)

chiru@chiru ~ $ js num.js 28
28: fourteen plus fourteen times one
chiru@chiru ~ $ js num.js 7
7: impossible
chiru@chiru ~ $ js num.js 42
42: nine thousand sixty minus nine thousand eighteen

Ve her sayı çalışması hangi ile numara görmek için, sadece bir göz sıkıcı cevap için js num.js 1337:

1337: ten plus one thousand three hundred twenty seven times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one

Sağlanan kodlar, verilen aralık için geçerli çözümler üretir (ve muhtemelen üstte, yalnızca değişkenin değerini yükseltmeniz gerekir L).

İstatistik

Bu bölüm verilen aralıktaki her sayı için bir çözüm bulmaktan sorumlu olduğu için , ifadelerin "ne kadar sıkıcı " olduğunu (veya: times onebu algoritma içinde ifade başına alt dizenin ne kadar kullanıldığını) ilgilendim . Kendiniz görün:

x : n'inci ifade (min. 0, maks. 10.000)

y : ifade içinde "kez bir" alt dizesinin oluşum sayısı (min. 0, maks. 1245)

grafik

Sonuç:

  • İfadeler doğrusal bir şekilde gittikçe sıkıcı olmaya meyillidir.
  • Çözeltilerin% 99'dan fazlası sıkıcıdır.

2
4 için bir çözüm varfour
FUZxxl

@FUZxxl Bunu hiç inkâr etmedim. Yanıt vermeniz durumunda If it does, return the words (4 is the only number with this property, unfortunately)bu bölümü yanlış anlamış olabilirsiniz. Bu 4, kendi çözümünü oluşturan operatörsüz tek ifade olduğunu söylüyor .
Chiru

@FUZxxl Oh, tamam. Az önce başlangıç ​​kısmında X = [0; 10] ∪ {12}, daha sonra da 4bunun bir çözümü olduğunu söylüyorum . Aralığı düzelttim, teşekkürler. :)
Chiru

6

C, 450 karakter

Düzenle: kaldırıldı zero

Düzenleme: yalnızca plusveminus

Karakter ekleyen ve koşulu doğru tutan en kısa ifadeyi aradım. Bulduğum plus ten plus fiveuzun 15 ve dizeye 15 ekler.

Sadece imkansız olmayan ilk 15 sayı için, herhangi bir sayıyı ifade etmek istiyorum. 12 imkansız en büyük sayıdır, bu nedenle 28'den küçük sabit kod numaralarına yeterlidir.

4 = dört
11 = altı artı beş
13 = sekiz artı beş
14 = yirmi eksi altı
15 = yirmi eksi beş
16 = onsekiz eksi iki
17 = on dört artı üç
18 = yirmi iki eksi dört
20 = otuz iki eksi on iki
21 = yirmi artı iki eksi bir
22 = yirmi artı dört eksi iki
23 = otuz eksi sekiz artı bir
24 = yirmi artı sekiz eksi dört
25 = yirmi artı sekiz eksi üç
27 = yirmi sekiz eksi altı artı beş

Yukarıdaki sayıların her biri> 27 olan x * 15 + sayılarını yazabiliriz.

golfed

#define P" plus "
#define M" minus "
#define U"four"
#define F"five"
#define E"eight"
#define W"twenty"
#define A"ten"P F P
*e[]={0,0,0,0,U,0,0,0,0,0,0,F P"six",0,E P F,W M"six",W M F,E"een"M"two",U"teen"P"three",W" two"M U,A U,"thirty two"M"twelve",W P"two"M"one",W M"two"P U,"thirty"P"one"M E,W P E M U,W M"three"P E,A F P"six",W" "E M"six"P F};main(n){n=atoi(1[(int*)1[&n]]);for(printf("%d: ",n);n>27;n-=15)printf(A);puts(e[n]?e[n]:"impossible");}

Okunabilir Kod

#include <stdio.h>
#include <stdlib.h>

// add fifteen to string, both as value and as character count (without spaces)
const char *add_fifteen = "plus ten plus five";

// table with hardcoded expressions
// NOTE: we could calculate 19, 26, 28 and 29 from 4, 11, 13 and 14
// but we would need more logic, so we hardcode those 4 numbers too.
const char *expressions[30]={"impossible", "impossible", "impossible", "impossible",
    "four", "impossible", "impossible", "impossible", "impossible",
    "impossible", "impossible", "five plus six", "impossible",
    "eight plus five", "twenty minus six",
    "fourteen plus one", "eighteen minus two", "fourteen plus three",
    "twenty two minus four", "four plus ten plus five",
    "thirty two minus twelve", "nine plus seven plus five",
    "twenty plus four minus two", "twelve plus seven plus four",
    "twenty plus eight minus four", "twenty plus eight minus three",
    "five plus six plus ten plus five", "twenty eight minus six plus five",
    "eight plus five plus ten plus five", "seven plus seven plus ten plus five"};

int main(int argc,char *argv[])
{
    int n = strtol(argv[1], NULL, 0);
    int fifteens = 0;

    printf("%d: ", n);

    // how many times do we need to add fifteen?
    if(n>29){
        fifteens=(n/15) - 1;
        n -= fifteens*15; // ensure 30 > n >= 15, so we don't get "impossible"
    }

    // look up the expression for n
    printf("%s", expressions[n]);

    // add fifteens till we are done
    while(fifteens-- > 0) {
        printf(" %s", add_fifteen);
    }

    printf("\n");
    return 0;
}

2
Kodunuzun nasıl çalıştığından tam olarak emin all numbers used in the output must be positive integersdeğilsiniz , ancak soruda belirtildiği gibi , #define Z "zero"kodunuzu Z örnekleriyle birlikte kaldırabilirsiniz, çünkü hiç kullanmamalısınız?
Qwix

"artı oniki" 12 harftir. Bu, kodunuzun kısaltılmasına yardımcı olur mu?
isaacg

Daha kısa yapardım, ne yazık ki boşluklar sayılmaz, plus twelvesadece 10 harftir
Optokopper

Tamam, kuralları yanlış okudum.
isaacg
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.