Konwertuj do iz systemu liczb czynnikowych

27

System liczb czynnikowych , zwany również silnikiem, jest mieszanym systemem liczbowym. Silnia określają wartość miejsca liczby.

W tym systemie najbardziej prawą cyfrą może być 0 lub 1, drugą prawą cyfrą może być 0, 1 lub 2 itd. Oznacza to, że ncyfrowa liczba czynnikowa może mieć maksymalną wartość (n + 1)!.

Na przykład, aby przekonwertować liczbę czynnikową 24201na dziesiętną, wykonaj następujące czynności:

2 * 5! = 240
4 * 4! = 96
2 * 3! = 12
0 * 2! = 0
1 * 1! = 1
240 + 96 + 12 + 0 + 1 = 349

Stąd liczba czynnikowa 24201jest 349podstawą 10.

Aby przekonwertować liczbę dziesiętną ( 349na przykład) na liczbę czynnikową, wykonaj następujące czynności:

Weź największą silnię mniejszą niż liczba. W tym przypadku jest to 120lub 5!.

349 / 5! = 2 r 109
109 / 4! = 4 r 13
13 / 3! = 2 r 1
1 / 2! = 0 r 1
1 / 1! = 1 r 0

Stąd 349podstawą 10jest liczba czynnikowa 24201.

Twoim zadaniem jest stworzenie najkrótszego programu lub funkcji, która konwertuje liczbę wejściową na drugą bazę.

Dane wejściowe będą ciągiem reprezentującym nieujemną liczbę całkowitą. Liczba czynnikowa będzie poprzedzona znakiem !(np. !24201), Podczas gdy liczba dziesiętna nie będzie poprzedzona niczym. Możesz założyć, że maksymalne dane wejściowe będą 10! - 1- 3628799dziesiętne i 987654321czynnikowe. Oznacza to, że litery nie będą pojawiać się na wejściu / wyjściu czynnikowym.

Program nie musi !dodawać wyniku do wartości faktograficznej i może generować ciąg znaków lub liczbę całkowitą. Dane wejściowe mogą mieć dowolny rozsądny format.


Przypadki testowe:

Input: 1234
Output: 141120

Input: 746
Output: 101010

Input: !54321
Output: 719

Input: !30311
Output: 381
Zmienność
źródło

Odpowiedzi:

10

APL, 39 37 znaków

{A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}

Przykłady:

      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'1234'
141120
      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'!54321'
719
Howard
źródło
1
Myślę, że można zastąpić ⍴⍵∩'!'z '!'∊⍵zapisać charakter.
Zmienność
@ Lotność Tak, możesz. Znalazłem też inny.
Howard
11
IMO posiadające w skrypcie słowo „pwn” jest warte dodatkowego znaku.
ejrb
1
Zgadzam się z ejrb. Czy mógłbyś to zepsuć?
Tytus
1
Wymień ~'!'się ∩⎕Dzapisać charakter.
Adám
9

Python 2.7 ( 163 157 152)

i=raw_input()
exec("b='';a=362880;j=int(i);x=9;"+'b+=`j//a`;j%=a;a/=x;x-=1;'*9,"a=x=1;b=0;"+'b+=a*int(i[-x]);x+=1;a*=x;'*~-len(i))['!'in i]
print int(b)

Bardziej czytelna wersja:

i=raw_input()
if'!'in i:a=x=1;b=0;c='b+=a*int(i[-x]);x+=1;a*=x;'*~-len(i)
else:b='';a=362880;j=int(i);x=9;c='b+=`j//a`;j%=a;a/=x;x-=1;'*9
exec c;print int(b)

Awaria:

Factoradic -> Decimal, when i is in the form !(number)
a=1   #Factorial value (multiplied every iteration)
x=1   #Index value
b=0   #Output
iterate ~-len(i) times:    #PSEUDOCODE! bitwisenot(a) = ~a = -a-1
    b+=a*int(i[-x])        #add the value of the xth last character in the factoradic #
    x+=1                   #Increment x
    a*=x                   #Set a to x!, (x-1)! * x = x!

Decimal -> Factoradic
b=''                       #Output
a=362880                   #Factorial value, set to 9! here
j=int(i)                   #Integer value of the input
x=9                        #Index value
iterate 9 times:           #PSEUDOCODE! This block is in an exec() loop
    b+=`j/a`               #Add floor(j/a) to b
    j%=a                   #Take out all multiples of a in j
    a/=x                   #Set a to (x-1)!, x! / x = (x-1)!
    x-=1                   #Decrement x
beary605
źródło
1
Niezłe rozwiązanie. Myślę, że można zastąpić '!'==i[0]z '!'in i, i może korzystać a=x=1. Ponadto nie potrzebujesz nawiasów wokół instrukcji exec.
grc
1
Można również wymienić (len(i)-1)się ~-len(i).
Zmienność
@Volatility, grc: Dzięki! Powinienem nauczyć się moich operatorów bitowych :)
beary605
1
Dobra odpowiedź, mogłem spróbować zastąpić instrukcję if (a,b)['!'in i]i udało mi się ogolić 6 znaków. Nie jest tak czytelny, jak to było ... link do pastebin
ejrb
@erjb: Dzięki za sugestię! Użyłem 2-krotek z kodem jako łańcucha w wierszu z funkcją exec, która zapisuje dwa kolejne znaki :)
beary605
8

GolfScript ( 48 44 43 znaków)

.~\{1{):?\.?%\?/@}9*{*+}+9*}:^{:N,{^N=}?}if

To jest samodzielny program. Konwersja czynnikowa => dziesiętna jest dość wolna, ponieważ wykonuje wyszukiwanie przy użyciu konwersji dziesiętnej => zamiast bezpośredniej konwersji podstawowej.

Format wejściowy pozwala na bardzo krótki przełącznik trybu: .~kopiuje ciąg wejściowy i ocenia go, więc jeśli dane wejściowe to tylko liczba, to np. "1234" 1234Na stosie, a jeśli zaczyna się od !(logicznie nie, z żadnym niepustym string jest prawdą) kończymy np. 0 30311na stosie. Zatem wartość na dole stosu jest prawdziwa dla dziesiętnej => czynnikiadyczny i fałsz dla czynnikowej => dziesiętny.

Peter Taylor
źródło
4

PHP <7,1 178 171 170 168 164 155 147 144 138 126 123 123 bajtów

for($b=$j=1,$i=strlen($x=$argn);+$x?$b<=$x:--$i;$b*=++$j)$r+=$x[$i]*$b;if(+$x)for(;$j>1;$x%=$b)$r.=$x/($b/=$j--)|0;echo+$r;

Uruchom jako potok -rlub przetestuj go online .

  • rozszerzenie nie jest wymagane
  • nie jest wymagana żadna funkcja podrzędna : podstawa czynnikowa jest ponownie wykorzystywana (zwiększana / zmniejszana w pętlach)
  • czysta liczba całkowita i arytmetyka ciągów, powinna nawet działać w php 3 (i nadal działa w php 7):
  • dziesiętne 0 zwraca pusty ciąg zamiast 0. (obie inne odpowiedzi PHP też.) Jeśli jest to niedopuszczalne, dodaj +5 dla dodatkowego przypadku.

bez golfa:

// two loops in one: compute the decimal number from a factorial
// or find the first factorial larger than a decimal $x
// the latter inits $r with '0': $i=strlen -> $x[$i]=='' -> (int)$x[$i]==$x[$i]*$b==0
// $b is the current digit´s base; $j is the bases´ latest factor
for($b=$j=1,$i=strlen($x=$argn);+$x?$b<=$x:--$i;$b*=++$j)
    $r+=$x[$i]*$b;
// and now for dec->fact ...
if(+$x)
    for(;$j>1;$x%=$b)
        // both $b and $j are one step too far in the first iteration;
        // -> decrement must precede the actual loop body
        // -> can be merged into the digit calculation -> all braces golfed
        $r.=$x/($b/=$j--)|0;
        // now: go on with the remainder (see loop head)
echo+$r; // final type cast removes leading zeros (from the first loop)
    // and fixes the '0' result (no operations at all on that input!)

porzucone pomysły na golfa:

  • $b<=$x-> $b<$x(-1)
    rozbija czyste silniki dziesiętne (tj. Te, które dają liczbę silni z tylko jedną cyfrą niezerową). Cierpi na to rozwiązanie JMPC; HamZa nie.
  • floor($x/$b)-> (int)($x/$b)
    może być nieco szybsze, ale rzutowanie tekstu poprzedza podział, więc potrzebuję nawiasów i nie zyskuję bajtu.
    $x/$b|0Zrób sztuczkę
  • Pętla de facto -> dec jest podobna do znalezienia silni w dec -> fakt. Ten sam przyrost, ciało nie ma znaczenia, ale niestety różne ustawienia wstępne i różne warunki postu. Dang; mogłem tam zagrać w golfa -21.
    YAY znalazłem rozwiązanie. Grałem trochę w golfa, ale odciąłem kolejne -4 (nr: -9) i zamknąłem wszystkie błędy / luki.

Czy jest jeszcze większy potencjał ... czy skończyłem grać w golfa?

Tytus
źródło
@ JörgHülsermann Dzięki za podpowiedź.
Titus
1
+$rzamiast $r|0zapisać jeden bajt. To samo dlaif($x|0)
Jörg Hülsermann
3

JavaScript (ES 6) 139 137 122 113 111

wypróbowałem inne podejście, używając magii tablic; ale skończyło się na 174 172 bajtach z tym:

f=x=>{if('!'==x[0]){a=x.split``.reverse();i=b=1;r=0;a.pop();a.map(d=>{r+=d*b;b*=++i})}else{t=[];for(i=b=1;b<=x;b*=++i){t.unshift(b)}r='';t.map(b=>{r+=x/b|0;x%=b})}return r}

Więc właśnie wziąłem mój kod PHP i przetłumaczyłem go. Mógłby usunąć wszystkie $i kilka ;, ale konieczność zainicjowania Varsa pochłonęła niektóre z tych korzyści. Udało się jednak golfowi uzyskać obie odpowiedzi nieco dalej.

grał w golfa

f=x=>{for(r=0,b=j=1,i=x.length;x|0?b<=x:--i;b*=++j)r+=x[i]*b;if(x|0)for(r='';j>1;x%=b)r+=x/(b/=j--)|0;return r}
  • pierwsza wersja zwraca „” po przecinku 0; dodaj +2, aby naprawić
  • druga wersja wymaga wprowadzenia ciągu znaków
  • oba testowane w Firefox, Edge i Opera

bez golfa

f=x=>
{
    for(r=0,b=j=1,i=x.length;x|0?b<=x:--i;b*=++j)
        r+=x[i]*b;
    if(x|0)
        for(r='';j>1;x%=b)
            r+=x/(b/=j--)|0;
    return r
}

pakiet testowy

<table id=out border=1><tr><th>dec</th><th>result<th>expected</th><th>ok?</th></tr></table>
<script>
    addR=(r,s)=>{var d=document.createElement('td');d.appendChild(document.createTextNode(s));r.appendChild(d)}
    test=(x,e)=>{var y=f(x),r=document.createElement('tr');addR(r,x);addR(r,y);addR(r,e);addR(r,e==y?'Y':'N');document.getElementById('out').appendChild(r)}
    samples={'349':'24201','1234':'141120','746':'101010','719':'54321','381':'30311','24':'1000','0':'0'};
    for(d in samples){test(d,samples[d]);test('!'+samples[d],d)}
</script>
Tytus
źródło
1
ES5 nie ma oznaczenia strzałki IIRC. A jeśli zamierzasz używać ES6, to .split('')=>.split``
Zacharý
@ Zacharý Gna Powinienem zauważyć, w jakiej przeglądarce testowałem to ... prawdopodobnie Firefox lub Opera. Więc ES 6?
Tytus
Tak, notacja strzałek to ES6.
Zacharý
1
Och, to mnie zaskoczyło. Myślałem, że blok kodu u góry jest twoim rozwiązaniem! Niezależnie od tego, nie sądzę, że musisz powiedzieć f=. Ponadto może r+=(x/(b/=j--)|0)być r+=x/(b/=j--)|0?
Zacharý
2

Perl 6 , 66 65 60 bajtów

-1 bajt dzięki Jo King

{/\!/??:1[.flip.chop.comb Z*[\*] 1..*]!![R~] .polymod(2..*)}

Wypróbuj online!

nwellnhof
źródło
1

GolfScript, 69 znaków

10,1>{1$*}*](.0=33={1>01/-1%0\{~@(@*@+}/\}{~\-1%{1$<},{1$1$/@@%}/}if;

Pobiera dane ze STDIN jak zwykle i drukuje wynik. Test online .

Howard
źródło
1

Haskell, 221 znaków

Code Golf

m v@(a:b)|a=='!'=(sum.zipWith(*)g.map(read.(:[])).reverse) b|True=(fst.until((<0).fst.snd)(\(s,(i,b))->(s*10+b`quot`f i,(i-1,b`rem`f i))).(\n->(0,((1+).last.takeWhile((n>=).f)$[1..], n))).read) v;g=scanl1(*)[1..];f=(g!!)

Stosowanie

$ ghci factorial.hs
ghci> m "1234"
 141120
ghci> m "!54321"
 719

Nieskluczony kod

parse v@(a:b) | a == '!' = to b
              | otherwise = from v

to = sum . zipWith (*) factorials . map (read . (:[])) . reverse

from = fst . until finished next . boostrap . read
    where finished = ((<0) . fst . snd)
          next (s,(i,r)) = (s * 10 + r `quot` factorial i, (i-1 ,r `rem` factorial i))
          bootstrap n = (0, (lastFact n, n))
          lastFact n = (1+) . last . takeWhile ((n>=) . factorial) $ [1..]

factorials = scanl1 (*) [1..]

factorial = (factorials!!)
StreakyCobra
źródło
Zdecydowanie najbardziej czytelny wpis. Haskell FTW!
Soham Chowdhury
1

Mathematica 213 177 175

Liczba czynnikowa jest zawijana f[], niezależnie od tego, czy jest to wejście, czy wyjście.

g@{n_,j_,r_}:=If[j==0,FromDigits@r,g@{q=QuotientRemainder[n,j!];q[[2]],j-1,Append[r,q[[1]]]}]
z@n_:=If[!IntegerQ@n, g[{n[[1]],9,{}}], f@Tr@(p=1;# (p++)!&/@Reverse@IntegerDigits@n)]

Stosowanie

z[24201]

f [349]

z[f[349]]

24201

Konwersja silni na liczbę dziesiętną . QuotientRemainder[n,j!]rekurencyjnie działa na cyfry liczby silni od lewej do prawej, zmniejszając się jz każdym krokiem. QuotientRemainder[349, 5!], na przykład zwroty {2, 109}i tak dalej.

Konwersja liczby dziesiętnej na silnią . Przesuwając się od prawej do lewej, funkcja czysta # (p++)! &mnoży każdą cyfrę #przez odpowiednią silnię.

DavidC
źródło
1

Python, 128 znaków

Uruchomienie zajmuje około pół godziny, ale jest niewielkie:

A=[`x`for x in xrange(10**9)if all(x/10**d%10<d+2 for d in range(9))]
i=raw_input()
print A.index(i[1:])if'!'in i else A[int(i)]

Tworzy listę wszystkich <= 9-cyfrowych liczb czynnikowych w kolejności numerycznej, a następnie wykonuje wyszukiwanie lub indeks do konwersji.

Jeśli chcesz przetestować, wystarczy wymienić 10**9z 10**6i ograniczać się do 6-cyfrowych numerów o zmiennej liczbie argumentów.

Mógłbym technicznie uratować postać, używając range(10**9)zamiast xrange(10**9). Nie próbuj tego w domu.

Keith Randall
źródło
Pomiędzy d+2ifor
Zacharý
1

PHP 231 214 204

Najnowsza odpowiedź

function g($x){return $x?$x*g($x-1):1;}function f($x,$e){if($x[0]=="!"){for($t=1;$t<$c=strlen($x);$t++){$e+=$x[$t]*g($c-$t);}}else{while(g(++$p)<=$x);while(--$p){$e.=floor($x/g($p));$x%=g($p);}}return$e;}

Stara odpowiedź

 function f($n){if($n[0]=="!"){$n=str_split($n);$c=count($n);$f=$y=1;while($c-->1){$e+=($f*$n[$c]);$f*=++$y;}return$e;}else{for($i=$c=1;$i<$n;$i*=$c){$r[$c++]=$i;}foreach(array_reverse($r)as$t){$e.=floor($n/$t);$n=$n%$t;}return$e;}}

Przykład

echo f('349')."\n"
    .f('!24201')."\n"
    .f('1234')."\n"
    .f('746')."\n"
    .f('!54321')."\n"
    .f('!30311');

Wydajność

24201
349
141120
101010
719
381
JPMC
źródło
2
Liczę 212 za nową odpowiedź, a nie 214. $ e nie wymaga inicjalizacji (-6) i foreach(range())można ją zastąpić prostą forpętlą (-9). Jednak podoba mi się ten pomysł.
Tytus
2
zły wynik dla czystych silni. 24powinien wrócić, 1000ale wraca 400. naprawić: g(++$p)<$x-> g(++$p)<=$x(+1)
Tytus
@Titus Dziękujemy za obie odpowiedzi! Zaktualizowałem swoją odpowiedź. Doceniam, że pomogłeś mi poprawić moją odpowiedź, kiedy twoja wydaje się znacznie lepsza.
JPMC
1
1) Ponownie liczę 2 od ciebie: 204, a nie 206. Czy do licznika bajtów dołączasz podział wiersza systemu Windows? 2) błąd składniowy w forkonstrukcji: ,powinien wynosić ;3) Mam kolejne 7 zmian oszczędzających 20 bajtów na tym kodzie. Chcę je?
Tytus
2
To właściwie tylko 5 zmian, ale jedna z nich ma trzy części. a) przestarzały drugi argument dla f () (-3) b) przestarzałe puste w funkcji g (-1) c) przestarzałe nawiasy klamrowe w gałęzi true (-4) d) zamień gałęzie true i false, odwróć ifwarunek, a następnie użyj my sexy type cast to int (-6) Nie wpłynie to na wynik dziesiętny 0! e) pozostały forkonstrukt można przepisać bardzo ładnie while(++$t<$c=strlen($x)): przyrost przed ciałem -> $ t nie wymaga inicjalizacji (-6)
Tytus
1

JELLY, 5 bajtów

Æ!ŒṘ€

Wyjaśnienie

Æ!ŒṘ€
Æ!     -Convert to factoriadic (list form)
  ŒṘ€  -Construct string

* Galaretka jest młodsza niż wiek pytania, dlatego moja odpowiedź nie jest konkurencyjna.

DaggerOfMesogrecia
źródło
1
Witamy w PPCG! Myślę, że Jelly jest młodsza od tego wyzwania, dlatego powinieneś zaznaczyć swoją odpowiedź jako niekonkurującą.
Laikoni
Och, nie zdawałem sobie sprawy, że to była zasada. Zrobi.
DaggerOfMesogrecia,
Czy odpowiedzi na to wyzwanie nie powinny działać w obie strony? Wydaje się, że działa to tylko w jeden sposób; możesz to naprawić. (Osobna uwaga: jeśli konwertujesz między liczbami całkowitymi i łańcuchami w Galaretce, zwykle najkrótszym jest użycie kombinacji Vi .)
1

Galaretka , 15 bajtów

ḊV€;0Æ¡µÆ!ṖḌƊ¬?

Wypróbuj online!

Jak to działa

ḊV€;0Æ¡µÆ!ṖḌƊ¬?     Main link (monad). Input: integer or string
             ¬?  *) If the given input is a string, run 1); otherwise run 2)

ḊV€;0Æ¡  1) Factorial base -> integer
ḊV€         Remove "!" and map each char to number
   ;0       Append zero (this is needed to run the built-in correctly)
     Æ¡     Built-in conversion

Æ!ṖḌ  2) Integer -> factorial base
Æ!       Built-in conversion
  ṖḌ     Remove a zero at the end, and convert to decimal

Dlaczego *)działa

¬jest logicznie elementarne NIE. Gdy podano jedną liczbę całkowitą, staje się ona pojedynczym zerem, co jest fałszem. Jednak po podaniu łańcucha każdy element (znak) jest zamieniany na zero, a cały wynik jest tablicą zer, co jest prawdą.

Zero jako liczba całkowita jest szczególnym przypadkiem. Przechodzi przez ścieżkę „silnia -> liczba całkowita”, ale nadal daje zero, co jest poprawne.

Bez wbudowanej silni podstawy, 25 bajtów

⁵R!µ³%Ḋ:ṖUḌ
⁵R!ḋḊUV€ƊµÇ¬?

Wypróbuj online!

Jak to działa

⁵R!µ³%Ḋ:ṖUḌ  Aux. link (monad). Integer -> factorial base
⁵R!µ         Set (1..10)! as left argument
    ³%Ḋ:Ṗ    Compute each digit: (input % (2..10)!) // (1..9)!
         UḌ  Reverse and convert the digit array to decimal

⁵R!ḋḊUV€ƊµÇ¬?  Main link (monad).
         怪?  If the input is a string, apply the left chain;
               otherwise, apply the aux. link above
⁵R!            (1..10)!
   ḋ           Dot product with...
    ḊUV€Ɗ      Remove "!", reverse, map each character to digit
Bubbler
źródło
0

K, 102

"I"$,/$*:'|:'{{(x-y*g),g:_(x:*x)%y:*/1+!y}\[x,0n;|1+!{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]]}

Zdecydowanie można to poprawić.

k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 349
24201
k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 746
101010
k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 1234
141120
tartin
źródło
0

D (159 znaków)

int x(string n){import std.conv;int r,i=9,f=9*'鶀',d;if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}else{d=n.to!int;while(i){r=r*10+d/f;d%=f;f/=i--;}}return r;}

Bez golfa iz punktem wejścia do programu

Wszystkie argumenty wiersza poleceń są drukowane jako <original> -> <converted>. W rzeczywistości zaimplementowany jest tylko przecinek dziesiętny do faktadyczny x. Odwrotnie, po prostu wywołuje xwszystkie liczby dziesiętne (0 .. *), aż wynik będzie równy wartości wejściowej. Największe wejście zajmuje ~ 3 sekund (! 987654321).

Plik wykonywalny online: http://dpaste.dzfl.pl/46e425f9

void main(string[] args) {
    import std.stdio;
    foreach (arg; args[1 .. $]) {
        writefln("%s -> %s", arg, x(arg));
    }
}

int x(string n) {
    import std.conv;
    int r, i=9, f=9*'鶀', d;  // 鶀's Unicode index equals 8*7*6*5*4*3*2*1

    // If the first character value is less than 48 ('0') it should be a '!'.
    if (n[0] < 48) {
        // Call x with different input (0..*) until it matches our n.
        // r.text.x is rewritten as x(text(r)).
        while (r.text.x < n[1..$].to!int) r++;
    } else {
        d = n.to!int;
        // Try d / 9!, d / 8!, etc. just as in the problem description.
        while (i) {
            r = r*10 + d/f;
            d %= f;
            f /= i--;
        }
    }
    return r;
}
mleise
źródło
Myślę, że można zmienić string nna char[]njeden bajt (wiem, że się tu spóźniłem).
Zacharý
Myślę też, że if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}można if(n[0]<48)while(r.text.x<n[1..$].to!int)r++;zaoszczędzić dwa bajty.
Zacharý
0

VBA 225

Dzięki Tytusowi za pomoc! Wciąż szukam golfa.

Sub a(b)
Set w=WorksheetFunction
e=Len(b)
If IsNumeric(b) Then
i=0
For d=0To 8
h=w.Fact(9-d)
g=b Mod h
If g<b+i Then
i=1
f=f &Int(b/h)
b=g
End If
Next
Else
For d=2To e
f=f+w.Fact(e-d-1)*Mid(b,d,1)
Next
End If
MsgBox f
End Sub
Gaffi
źródło
Nie znam VBA, ale czy istnieje sposób na sprawdzenie bwartości liczbowej zamiast porównywania pierwszego znaku?
Tytus
@Tytus Istnieje kontrola numeryczna, a jej odpowiednikiem byłoby:, If Not IsNumeric(b) Thenale wymaga to więcej znaków. Teraz nie wszedłem i nie sprawdziłem ponownie całego kodu; może być nieco lepszy sposób na zrobienie tego z IsNumericogólnym. - Korekta, tutaj jest niewielka poprawa. Dzięki!
Gaffi,
Znalazłem kolejne cztery bajty: For d=9To 1Step-1i Fact(d)-> For d=0To 8i Fact(9-d)kolejne dwa, jeśli to zrobisz, For d=2To eiFact(e-d+1)*Mid(b,d,1)
Tytus
Czy typ rzutowany na Int może być napisany w inny sposób?
Tytus
@Titus Spójrz na siebie, krążysz wokół mnie. :) Poprawiam teraz ... Co do Int (), nie sądzę, że istnieje prostsza (mniejsza) metoda, nie.
Gaffi,
0

PHP , 124 bajty

for($f=1;("$">$a=$argn)&&~$c=strrev($a)[$n];)$r+=$c*$f*=++$n;for(;$a>=$f*=++$i;);for(;~-$i;$a%=$f)$r.=0|$a/$f/=$i--;echo+$r;

Wypróbuj online!

Rozszerzony

for($f=1;("$">$a=$argn)&&~$c=strrev($a)[$n];) # runs in case of "!" at the beginning
  $r+=$c*$f*=++$n; #reverse string multiply with the next factorial "!"*$f=0
for(;$a>=$f*=++$i;); # runs not in case of "!" at the beginning string comparing. search the factorial that is higher as input value
for(;~-$i;$a%=$f) # runs only when the second loop had runs
  $r.=0|$a/$f/=$i--; # concat the value of the division with the highest factorial used
echo+$r; # Output result
Jörg Hülsermann
źródło
0

Perl 6 , 150 bajtów

{/^\!/??([+] [Z*] .comb.skip.reverse,[\*] 1..*)!!(reduce
->\a,\b{a[0]~a[1] div b,a[1]%b},("",+$_),|(first
*[*-1]>$_,[\,] [\*] 1..*).reverse[1..*])[0]}
Sean
źródło
0

APL (NARS), 36 znaków, 72 bajty

{⍵⊆⎕D:10⊥(9..2)⊤⍎⍵⋄t+.×⌽!⍳≢t←⍎¨,1↓⍵}

wydaje się, że 10⊥ (9..2) ⊤ jest lepsze niż funkcja rekurencyjna, dzięki Howardowi dla innego rozwiązania APL, które pokazuje, że ... (nawet jeśli nie rozumiem w 100%). Wprowadź liczby bez „!” <10 !. Test:

  u←{⍵⊆⎕D:10⊥(9..2)⊤⍎⍵⋄t+.×⌽!⍳≢t←⍎¨,1↓⍵}    
  u¨'1234' '746' '!54321' '!30311' '!24201'    
141120 101010 719 381 349 
  u '0'
0
  u '!0'
0
  u '9'
111
  u '!111'
9
  u '!9'
9
RosLuP
źródło