แปลงเป็นและจากระบบตัวเลขแฟกทอเรียล


27

ระบบจำนวนปัจจัยที่เรียกว่า factoradic เป็นระบบเลข Radix ผสม แฟคทอเรียลกำหนดค่าสถานที่ของตัวเลข

ในระบบนี้ตัวเลขที่ถูกต้องที่สุดอาจเป็น 0 หรือ 1 หลักขวาสุดที่สองสามารถเป็น 0, 1 หรือ 2 และอื่น ๆ ซึ่งหมายความว่าnตัวเลขตัวประกอบตัวเลขสามารถมีค่าสูงสุด(n + 1)!ได้

ตัวอย่างเช่นในการแปลงจำนวนตัวประกอบ24201ให้เป็นทศนิยมคุณต้องดำเนินการดังนี้

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

ดังนั้นจำนวน factoradic 24201เป็นฐาน34910

ในการแปลงตัวเลขทศนิยม (พร้อม349ตัวอย่าง) เป็นตัวเลขตัวประกอบคุณต้องทำดังนี้

ใช้แฟกทอเรียลที่ใหญ่ที่สุดน้อยกว่าจำนวน ในกรณีนี้มันเป็นหรือ1205!

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

ดังนั้น349ฐานเป็นจำนวน10 factoradic24201

ความท้าทายของคุณคือการสร้างโปรแกรมหรือฟังก์ชั่นที่สั้นที่สุดที่แปลงหมายเลขอินพุตไปยังฐานอื่น

อินพุตจะเป็นการแทนสตริงของจำนวนเต็มที่ไม่เป็นลบ ตัวเลขตัวประกอบจะถูกนำหน้าด้วย!(เช่น!24201) ในขณะที่ตัวเลขทศนิยมจะไม่นำหน้าด้วยอะไร คุณอาจจะคิดว่าการป้อนข้อมูลสูงสุดที่จะเป็น10! - 1- 3628799ในทศนิยมและ987654321ใน factoradic ซึ่งหมายความว่าตัวอักษรจะไม่ปรากฏในอินพุต / เอาต์พุตตัวประกอบ

โปรแกรมไม่จำเป็นต้อง!เพิ่มเอาท์พุตที่เป็นตัวประกอบและอาจส่งออกสตริงหรือจำนวนเต็ม อินพุตอาจอยู่ในรูปแบบที่สมเหตุสมผล


กรณีทดสอบ:

Input: 1234
Output: 141120

Input: 746
Output: 101010

Input: !54321
Output: 719

Input: !30311
Output: 381

คำตอบ:


10

APL, 39 37 ตัวอักษร

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

ตัวอย่าง:

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

1
ฉันคิดว่าคุณสามารถแทนที่⍴⍵∩'!'ด้วย'!'∊⍵เพื่อบันทึกตัวละคร
ความผันผวน

@ ความผันผวนใช่คุณทำได้ ฉันพบอีกอันหนึ่ง
Howard

11
IMO ที่มีคำว่า "pwn" ในสคริปต์ของคุณนั้นคุ้มค่ากับอักขระพิเศษ
ejrb

1
ฉันเห็นด้วยกับ ejrb คุณจะทำลายมันลงได้ไหม
ติตัส

1
แทนที่~'!'ด้วย∩⎕Dเพื่อบันทึกอักขระ
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)

รุ่นที่อ่านเพิ่มเติมได้:

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)

ทำให้พังถล่ม:

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

1
ทางออกที่ดี ฉันคิดว่าคุณสามารถแทนที่'!'==i[0]ด้วยและสามารถใช้'!'in i a=x=1นอกจากนี้คุณไม่จำเป็นต้องใช้วงเล็บในคำสั่ง exec
grc

1
นอกจากนี้คุณยังสามารถใช้ทดแทนด้วย(len(i)-1) ~-len(i)
ความผันผวน

@ ความผันผวน, GRC: ขอบคุณ! ฉันควรจะเรียนรู้ผู้ประกอบการระดับบิตของฉัน :)
beary605

1
คำตอบที่ดีฉันใช้เสรีภาพในการพยายามแทนที่คำสั่ง if ด้วย(a,b)['!'in i]และจัดการเพื่อกำจัดอักขระ 6 ตัว มันไม่สามารถอ่านได้เหมือนอย่างที่มันเป็น ... pastebin link
ejrb

@erjb: ขอบคุณสำหรับคำแนะนำ! ผมใช้-tuple 2 ที่มีรหัสเป็นสตริงในสายที่มีฟังก์ชั่น exec ซึ่งจะช่วยประหยัดตัวละครทั้งสองมากขึ้น :)
beary605

8

GolfScript ( 48 44 43 ตัวอักษร)

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

นี่คือโปรแกรมที่มีในตัวเอง factoriadic => การแปลงทศนิยมค่อนข้างช้าเนื่องจากทำการค้นหาโดยใช้การแปลงทศนิยม => factoriadic แทนที่จะเป็นการแปลงฐานโดยตรง

รูปแบบการป้อนข้อมูลที่ช่วยให้สวิตช์โหมดสั้นมาก: .~สำเนาสายป้อนและประเมินมันดังนั้นถ้าใส่เป็นเพียงตัวเลขที่เราจบลงด้วยเช่น"1234" 1234ในกองและถ้ามันเริ่มต้นด้วย!(ตรรกะไม่ใด ๆ ที่ไม่ว่างเปล่า สตริงเป็นความจริง) เราลงท้ายด้วยเช่น0 30311ในกอง จากนั้นค่าที่ด้านล่างของสแต็กคือความจริงสำหรับทศนิยม => factoriadic และ falsy สำหรับ factoriadic => ทศนิยม


4

PHP <7.1 178 171 170 168 164 155 147 144 138 126 123 ไบต์

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;

ทำงานเป็นท่อที่มี-rหรือทดสอบออนไลน์

  • ไม่ต้องการส่วนขยาย
  • ไม่จำเป็นต้องใช้ฟังก์ชันย่อย : ฐานแฟคทอเรียลถูกนำมาใช้ซ้ำ (เพิ่ม / ลดลงในลูป)
  • เลขจำนวนเต็มและสตริง arithmetics ล้วนควรทำงานใน php 3 (และยังคงทำงานใน php 7):
  • ทศนิยม 0 0ผลตอบแทนสตริงว่างแทน (ทั้งคำตอบ PHP อื่น ๆ ก็ทำได้เช่นกัน) ถ้านั่นเป็นสิ่งที่ยอมรับไม่ได้ให้เพิ่ม +5 สำหรับกรณีพิเศษ

ungolfed:

// 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!)

ไอเดียการเล่นกอล์ฟที่ถูกทิ้งร้าง:

  • $b<=$x-> $b<$x(-1)
    จะแยกแฟคทอเรียลทศนิยมบริสุทธิ์ (เช่นที่ส่งผลให้ตัวเลขแฟคทอเรียลที่มีตัวเลขที่ไม่ใช่ศูนย์เพียงหนึ่งหลัก) โซลูชันของ JMPC ทนทุกข์ทรมานจากสิ่งนั้น HamZa ไม่ได้
  • floor($x/$b)-> (int)($x/$b)
    อาจเร็วขึ้นเล็กน้อย แต่พิมพ์การหล่อนำหน้าการหารดังนั้นฉันต้องการวงเล็บและไม่ได้รับไบต์
    $x/$b|0ไม่หลอกลวง
  • วนรอบในข้อเท็จจริง -> ธันวาคมคล้ายกับ factorial-find ใน dec-> ข้อเท็จจริง การเพิ่มขึ้นเหมือนกันร่างกายไม่สำคัญ แต่น่าเสียดายที่แตกต่างกันและเงื่อนไขการโพสต์ที่แตกต่างกัน แดง; อาจมี golfed -21 ที่นั่น
    ใช่ฉันพบวิธีแก้ปัญหาแล้ว เอาการเล่นกอล์ฟสักหน่อย แต่ตัดออกไปอีก -4 (ไม่ใช่: -9) และปิดบั๊ก / ช่องโหว่ทั้งหมด

มีโอกาสมากขึ้น ... หรือฉันเล่นกอล์ฟเสร็จแล้ว?


@ JörgHülsermannขอบคุณสำหรับคำใบ้
ติตัส

1
+$rแทนที่จะ$r|0บันทึกหนึ่งไบต์ เดียวกันสำหรับif($x|0)
JörgHülsermann

3

JavaScript (ES 6) 139 137 122 113 111

ลองวิธีอื่นโดยใช้เวทอาเรย์ แต่ฉันสิ้นสุดที่174 172 bytes ด้วยที่:

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}

ดังนั้นฉันจึงใช้รหัส PHP ของฉันและแปลมัน สามารถลบข้อมูลทั้งหมด$และบางส่วน;ออกได้ แต่ความจำเป็นในการเริ่มต้นใช้งาน vars กินผลประโยชน์บางส่วนนั้น แม้ว่าสนามกอล์ฟที่มีการจัดการจะสามารถตอบสนองต่อไปได้

แข็งแรงเล่นกอล์ฟ

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}
  • เวอร์ชันแรกส่งคืน '' สำหรับทศนิยม 0; เพิ่ม +2 เพื่อแก้ไข
  • รุ่นที่สองต้องการอินพุตสตริง
  • ทั้งทดสอบใน Firefox, Edge และ Opera

ungolfed

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
}

ชุดทดสอบ

<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>

1
ES5 ไม่มีเครื่องหมายลูกศร IIRC และถ้าคุณจะใช้ ES6 ดังนั้น.split('')=>.split``
Zacharý

@ Zacharý Gna ฉันควรจะสังเกตว่าเบราว์เซอร์ใดที่ฉันทดสอบใน ... อาจเป็น Firefox หรือ Opera ดังนั้น ES 6?
ติตัส

ใช่สัญลักษณ์ลูกศรคือ ES6
Zacharý

1
โอ้ที่ทำให้ฉันระวังฉันคิดว่าการบล็อกรหัสที่ด้านบนเป็นทางออกของคุณ! f=โดยไม่คำนึงถึงผมไม่คิดว่าคุณจำเป็นต้องพูด นอกจากนี้ยังสามารถr+=(x/(b/=j--)|0)เป็นr+=x/(b/=j--)|0?
Zacharý


1

GolfScript, 69 ตัวอักษร

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

รับอินพุตจาก STDIN ตามปกติและพิมพ์ผลลัพธ์ ทดสอบออนไลน์


1

Haskell, 221 ตัวอักษร

รหัสกอล์ฟ

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!!)

การใช้

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

รหัสที่ไม่ได้รับการปรับปรุง

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!!)

โดยรายการที่อ่านได้มากที่สุด Haskell FTW!
Soham Chowdhury

1

Mathematica 213 177 175

หมายเลขแฟคทอเรียลจะถูกห่อหุ้มf[]ไม่ว่าจะเป็นอินพุตหรือเอาต์พุต

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)]

การใช้

z[24201]

ฉ [349]

z[f[349]]

24201

แปลงของปัจจัยที่จะเลขทศนิยม QuotientRemainder[n,j!]ทำหน้าที่ซ้ำกับตัวเลขของจำนวนแฟคทอเรียลจากซ้ายไปขวาลดลงjในแต่ละขั้นตอน QuotientRemainder[349, 5!]เช่นผลตอบแทน{2, 109}และอื่น ๆ

การแปลงทศนิยมกับจำนวนปัจจัย การย้ายจากขวาไปซ้าย, ฟังก์ชั่น pure # (p++)! &, คูณแต่ละหลัก#ด้วยแฟคทอเรียลที่เหมาะสม


1

Python 128 ตัวอักษร

การดำเนินการนี้ใช้เวลาประมาณครึ่งชั่วโมง แต่มีขนาดเล็ก:

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)]

มันสร้างรายการของตัวเลขตัวประกอบตัวเลข <= 9 หลักทั้งหมดตามลำดับตัวเลขจากนั้นทำการค้นหาหรือดัชนีเพื่อแปลง

หากคุณต้องการทดสอบเพียงแทนที่10**9ด้วย10**6และ จำกัด ตัวคุณให้เป็นตัวเลข Variadic 6 หลัก

ผมในทางเทคนิคสามารถบันทึกตัวอักษรโดยใช้แทนrange(10**9) xrange(10**9)อย่าลองทำที่บ้าน


ไม่จำเป็นต้องใช้ช่องว่างระหว่างd+2และfor
Zacharý

1

PHP 231 214 204

คำตอบล่าสุด

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;}

คำตอบเก่า

 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;}}

ตัวอย่าง

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

เอาท์พุต

24201
349
141120
101010
719
381

2
ฉันนับ 212 สำหรับคำตอบใหม่ไม่ใช่ 214 $ e ไม่จำเป็นต้องเริ่มต้น (-6) และforeach(range())สามารถแทนที่ได้ด้วยforลูปแบบง่าย(-9) ฉันชอบความคิดนี้
Titus

2
ผลที่ผิดสำหรับแฟคทอเรียลที่บริสุทธิ์ 24ควรกลับแต่ผลตอบแทน1000 400การแก้ไข: g(++$p)<$x-> g(++$p)<=$x(+1)
Titus

@Titus ขอบคุณสำหรับคำตอบของคุณทั้งคู่! ฉันปรับปรุงคำตอบของฉัน ฉันขอขอบคุณที่คุณช่วยฉันปรับปรุงคำตอบของฉันเมื่อคุณดูเหมือนดีกว่า
JPMC

1
1) ฉันนับ 2 น้อยกว่าคุณอีกครั้ง: 204 ไม่ใช่ 206 คุณรวมตัวแบ่งบรรทัด Windows ในการนับไบต์ของคุณหรือไม่ 2) ข้อผิดพลาดทางไวยากรณ์ในการforสร้าง: ,ควรเป็น;3) ฉันมีการเปลี่ยนแปลงอีก 7 รายการที่บันทึก 20 ไบต์ในรหัสนั้น ต้องการมันไหม
ติตัส

2
จริง ๆ แล้วมันมีการเปลี่ยนแปลงเพียง 5 ครั้ง แต่หนึ่งในนั้นมีสามส่วน a) อาร์กิวเมนต์ที่ล้าสมัยครั้งที่สองสำหรับ f () (-3) b) ล้าสมัยในฟังก์ชัน g (-1) c) วงเล็บปีกกาล้าสมัยในสาขาที่แท้จริง (-4) d) สลับสาขาจริงและเท็จกลับifเงื่อนไขแล้วใช้ นักแสดงเซ็กซี่ของฉันส่งไปที่ int (-6) สิ่งนี้จะไม่ส่งผลต่อผลการค้นหาทศนิยม 0 จ) ที่เหลือforสร้างสามารถเขียนใหม่ด้วยดีมากwhile(++$t<$c=strlen($x)): เพิ่มขึ้นก่อนที่ร่างกาย -> $ T ไม่จำเป็นต้องเริ่มต้น (-6)
ติตัส

1

JELLY ขนาด 5 ไบต์

Æ!ŒṘ€

คำอธิบาย

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

* เจลลี่อายุน้อยกว่าอายุของคำถามดังนั้นคำตอบของฉันคือไม่ใช่การแข่งขัน


1
ยินดีต้อนรับสู่ PPCG! ฉันคิดว่าเจลลี่นั้นอ่อนกว่าความท้าทายนี้ดังนั้นคุณควรทำเครื่องหมายคำตอบว่าไม่ใช่การแข่งขัน
Laikoni

โอ้ฉันไม่ได้ตระหนักว่านั่นเป็นกฎ จะทำ.
DaggerOfMesogrecia

คำตอบสำหรับความท้าทายนี้ไม่ได้หมายถึงการทำงานทั้งสองวิธี? ดูเหมือนว่าจะทำงานเพียงทางเดียวเท่านั้น คุณอาจต้องการแก้ไข (ในบันทึกย่อแยกต่างหากหากคุณแปลงระหว่างจำนวนเต็มและสตริงใน Jelly ปกติแล้วจะเป็นการยากที่จะใช้การรวมกันของVและ.)

1

เยลลี่ 15 ไบต์

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

ลองออนไลน์!

มันทำงานอย่างไร

Ḋ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

ทำไมถึงได้*)ผล

¬ไม่ได้เป็นองค์ประกอบตรรกะฉลาด เมื่อได้รับจำนวนเต็มเดียวมันจะกลายเป็นศูนย์เดียวซึ่งเป็นเท็จ อย่างไรก็ตามเมื่อได้รับสตริงแต่ละองค์ประกอบ (ตัวอักษร) จะกลายเป็นศูนย์และผลลัพธ์ทั้งหมดคืออาร์เรย์ของศูนย์ซึ่งเป็นความจริง

ศูนย์เป็นจำนวนเต็มเป็นกรณีพิเศษ มันผ่านเส้นทาง "แฟกทอเรียล -> จำนวนเต็ม" แต่ก็ยังให้ศูนย์ที่ถูกต้อง

ไม่มีฐานแฟกทอเรียลขนาด 25 ไบต์

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

ลองออนไลน์!

มันทำงานอย่างไร

⁵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

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]]}

น่าจะปรับปรุงได้.

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

0

D (159 ตัวอักษร)

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;}

Ungolfed และมีจุดเริ่มต้นโปรแกรม

<original> -> <converted>ทั้งหมดอาร์กิวเมนต์บรรทัดคำสั่งจะถูกพิมพ์ออกมาเป็น มีการใช้งานทศนิยมแบบตัวประกอบตัวประกอบxเท่านั้น ในทางกลับกันเพียงแค่เรียกxกับตัวเลขทศนิยมทั้งหมด (0 .. *) จนกว่าผลลัพธ์จะเท่ากับอินพุต ใช้เวลาประมาณ 3 วินาทีในการป้อนข้อมูลที่ใหญ่ที่สุด (! 987654321)

เวอร์ชันออนไลน์ที่รันได้: 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;
}

ฉันคิดว่าอาจเป็นไปได้ที่จะเปลี่ยนstring nเป็นchar[]nบันทึกหนึ่งไบต์ (ฉันรู้ว่าฉันมาสาย)
Zacharý

นอกจากนี้ฉันคิดว่าif(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}สามารถif(n[0]<48)while(r.text.x<n[1..$].to!int)r++;ประหยัดสองไบต์ได้
Zacharý

0

VBA 225

ขอบคุณ Titus สำหรับความช่วยเหลือ! ยังคงมองหาการเล่นกอล์ฟเพิ่มเติม

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

ฉันไม่รู้ VBA แต่มีวิธีตรวจสอบbค่าตัวเลขแทนการเปรียบเทียบอักขระตัวแรกหรือไม่
ติตัส

@Titus มีการตรวจสอบตัวเลขและสิ่งที่เทียบเท่าที่นี่จะเป็น: If Not IsNumeric(b) Thenแต่นั่นต้องใช้อักขระมากขึ้น ตอนนี้ฉันไม่ได้เข้าไปตรวจสอบโค้ดทั้งหมดอีกครั้ง อาจมีวิธีที่ดีกว่าเล็กน้อยในการทำเช่นนี้IsNumericโดยรวม - แก้ไขมีการปรับปรุงเล็กน้อยที่นี่ ขอบคุณ!
Gaffi

ผมพบว่าอีกสี่ไบต์: For d=9To 1Step-1และFact(d)-> For d=0To 8และFact(9-d)และอีกสองถ้าคุณทำFor d=2To eและFact(e-d+1)*Mid(b,d,1)
ติตัส

ประเภทการส่งไปยัง Int สามารถเขียนด้วยวิธีอื่นได้หรือไม่?
Titus

@Titus มองคุณวิ่งวนรอบตัวฉัน :) ตอนนี้ฉันกำลังปรับแต่ง ... สำหรับ Int () ฉันไม่คิดว่าจะมีวิธีที่ง่ายกว่า (เล็กกว่า) ไม่ใช่
Gaffi

0

PHP , 124 ไบต์

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;

ลองออนไลน์!

ขยาย

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


0

APL (NARS), 36 ตัวอักษร, 72 ไบต์

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

ดูเหมือนว่า10⊥ (9..2) ⊤นั้นดีกว่าฟังก์ชั่นวนซ้ำเนื่องจาก Howard สำหรับโซลูชัน APL อื่น ๆ ที่แสดงว่า ... (แม้ว่าฉันจะไม่เข้าใจ 100%) ใส่ตัวเลขโดยไม่ต้อง '!' <10 !. ทดสอบ:

  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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.