dc , 47 bayt
dc , 48 bayt
Ayrıca Bash + Unix yardımcı programları, 29 bayt
dc (47 bayt):
1sb[_1sb]s zz?sdlb*sc[pld+lnx]sl[dlb*lcr<l]dsnx
Çevrimiçi deneyin!
Eksi işareti yerine negatif sayıların alt çizgi ile girilmesi gerektiğine dikkat edin, çünkü dc sayısal girişi kabul eder. Bu nedenle, örneğin, -5 yerine _5 yazın.
dc bir değişkene karakter veya string girişi okuyamaz ve işleyemez (aşağıda daha ayrıntılı bir açıklama vardır), ancak bunun üzerinde çalışmanın iki yolunu buldum:
47 baytlık DC çözeltisi argument1 vardır ve sınırlayıcı olarak boşluklu, ters argument2 giriş çalışır. Bu nedenle, 1'den 1'e (ancak dahil değil) saymak, 3'lük adımlarla 10 olarak girilir:
< 1 10 3
Bağımsız değişkenlerin sırasını değiştirmek kabul edilemezse, bağımsız değişkenlerin orijinal sırasını koruyan 48 baytlık bir dc çözümü de veriyorum . Bu zz
, argümanlar arasındaki sınırlayıcı olarak kullanır . Bu yüzden 1'den 3'e kadar (ancak dahil değil) 10'dan tekrar saymak aşağıdaki giriş satırını kullanır:
1zz<zz10zz3
Son olarak, aynı fikirler 29 baytlık bir bash çözümü sunar .
Dc'nin string işleme eksikliğinin ve bu programın bununla nasıl başa çıktığına ilişkin detaylar:
Bu sorunu dc'de kullanmak zordur, çünkü dc çoğu dilde olduğu gibi string veya char girdisini kabul etmez. Dc bir giriş dizesini okuduğunda, hemen bu dizeyi bir dc programı (makro) olarak çalıştırır ve sonra dizeyi atar. Dizenin karakterlerini bellekte saklayamaz ve daha sonra veya başka bir şekilde işleyemezsiniz. Bu, girişte '<' veya '>' olması şartına müdahale eder.
Bunun etrafında iki yol göstereceğim. Yukarıdaki çözümde (47 bayt), ilk iki girişin sırasını değiştiriyoruz. Giriş sınırlayıcı, boşluk karakteridir. Örneğin, 1'den 3'e kadar (ancak dahil değil) 10'dan 3'e kadar saymak için,
< 1 10 3
İşte bu çözümün arkasındaki fikir:
Dc'deki makrolar kayıtlarda saklanır ve kayıtların tek karakterli adları vardır. Makroyu, adı yalnızca boşluk karakteri olan kayıt defterinde saklarım.
Program girişi almadan önce yığında 0 ve 1 tuşlarına basarak çalışır. Ardından, giriş bir dc programı olarak çalıştırıldığında (bu, dc'nin giriş satırlarıyla yaptığı şeydir), '<' veya '>' karakteri, komutun adıdır; '<' veya '>' sonrası sonraki karakter. Özellikle, yığındaki ilk iki öğe atılır. Açılan ilk öğe <(sırasıyla,>) ise, ikinci öğe açılan ise, belirtilen makro yürütülür. Bir sonraki karakter ('<' veya '>' işaretinden sonra) bir boşluktur, yani adı char olan boşlukta kaydettiğimiz makro, koşul geçerliyse yürütülen karakterdir. Ama yığına 0 ve 1 ittik, bu yüzden ilk atılan madde 1, ikinci atılan madde ise 0 oldu. Makro yalnızca koşullu test> ise <değil, yürütülür. Bu, girişteki '<' ve '>' arasındaki farkı ayırt etmemizi sağlar.
Satırdaki kalan öğeler yalnızca rakamlardır ve dc bu sayıları yığına sırayla basar.
İşte ayrıntılı bir açıklama. Çoğu zaman, sayma değişkeni (problem ifadesinde sözde koddaki i) yığının en üstünde saklanır.
1sb Store 1 in register b. (b will end up being 1 for '<', and -1 for '>').
[_1sb]s Note that there is a space after the second s. So the space char is the name of a macro which stores -1 in b.
z Push 0 on the stack.
z Push 1 on the stack.
? Accept input in the format above. This will:
- Store 1 or -1 in b, depending on whether you've typed "<" or ">"
- Push each of the three numbers in turn on the stack.
sd Save the increment in register d.
lb*sc Save either limit or -limit in register c, depending on whether the input started with "<" or ">".
[pld+lnx]sl Define a macro called l which is the body of our loop:
- Prints the top of the stack
- Adds the increment to the top of the stack.
- Calls macro n (the loop test).
[dlb*lcr<l]dsn Define a macro called n which is the test of the loop:
It checks to see if i (at the top of the stack) times b is less than c; if so, it calls macro l (looping back).
x Execute the loop test macro initially (a while loop needs to have a test at the top before entering the loop the first time).
Öte yandan, OP belirtti:
Input can be in one-line using any format "a/b/c/d" or "a,b,c,d" etc.
Bu yüzden belki siparişi değiştirmek ve girdiden önce b'yi almak meşru değildir.
İşte a, b, c ve d'yi orijinal sıralarında tutan bir alternatif. Herhangi bir sınırlayıcı kullanmamıza izin verilir; Sınırlayıcı olarak zz kullanacağım. Bu nedenle, 1'den 1'e (ancak dahil değil) saymak, 3'lük adımlarla 10 olarak girilir:
1zz<zz10zz3
Zz ile ayrılmış girdili yeni program
dc (48 bayt):
1sb[_1sb]sz?sdiilb*sci[pld+lnx]sl[dlb*lcr<l]dsnx
Bu, 47 bayt ilk çözümden daha uzun bir bayttır.
Zz-ayrılmış sürümünü çevrimiçi olarak deneyin!
Şahsen farklı sıradaki < 1 10 3
formatlamanın problemin özünde olduğunu düşünüyorum , ancak 1zz<zz10zz3
teknik şartnamenin yerine getirilmesi daha iyi olabilir.
Farklı girdi argümanları arasında farklı sınırlayıcılara izin verirseniz, muhtemelen daha kısa bir çözüm elde edebilirsiniz, ancak bunun sorunun özünde olduğunu sanmıyorum.
Bash + Unix yardımcı programları, 29 bayt
Yukarıdaki fikri bir bash programına dönüştürebilirsiniz (bu, dc çağırır); bu, "<" ve ">" ile ilgili tüm zorluklardan kaçınır ve ayrıca çeşitli sayısal parametrelerin kullanılmasını da kolaylaştırır, bu nedenle @ zeppelin bash + bc cevabıyla aynı, sadece 29 bayt uzunluğundadır.
bash versiyonu (29 bayt):
dc -e[p$4+d$3r$2l]sl$1d$3r$2l
Çevrimiçi bash sürümünü deneyin!
Bash programının içindeki dc programının nasıl çalıştığının bir açıklaması:
İ değeri çoğu zaman yığının en üstünde depolanır.
[ Start of macro (i is at the top of the stack). This macro will be called l.
p Print i
$4+ i += (4th argument)
d Duplicate i at the top of the stack.
$3 Push the 3rd argument onto the stack.
r Swap the top two items on the stack, so i is at the top and arg3 is second
$2l $2 is "<" or ">", causing the top two items to be popped from the stack, and macro l is then called (effectively looping back) if i < arg3 or i > arg3, respectively.
]sl End of macro definition; store macro in register l.
$1 Push argument 1 onto the stack (i = 1st argument).
d$3r$2l Just as above, call macro l if i < arg3, or i > arg3, depending on whether arg2 is "<" or ">"