สร้างเครื่องคิดเลข omnifix


16

แรงบันดาลใจ ผกผัน

ประเมินนิพจน์ omnifix ที่กำหนด

Omnifix เป็นเหมือนสัญกรณ์คณิตศาสตร์มัดปกติ แต่มีสำเนาเพิ่มเติมของแต่ละสัญลักษณ์รอบข้อโต้แย้ง สัญลักษณ์ด้านนอกเกิดขึ้นในวงเล็บดังนั้นจึงไม่จำเป็นต้องใช้วงเล็บเพิ่มเติม

คุณต้องรองรับการบวกการลบการคูณการหารและจำนวนจริงที่เป็นบวก (สามารถลบได้-0-n-) ในช่วงที่เหมาะสมสำหรับภาษาของคุณ

บวกและลบจะต้องเป็น+และ-แต่คุณอาจใช้*หรือ×บางครั้งและ/หรือ÷สำหรับการหาร สัญลักษณ์อื่นที่สมเหตุสมผลจะได้รับอนุญาตเมื่อมีการร้องขอ

จุดบราวนี่สำหรับคำอธิบายและคุณสมบัติเพิ่มเติม (เช่นการดำเนินการเพิ่มเติมจำนวนลบสตริง ฯลฯ ) แม้ว่าคำตอบของคุณจะไม่มีฟีเจอร์เหล่านี้ แต่อย่าลังเลที่จะแสดงความสามารถ

โปรดระบุลิงก์เพื่อทดสอบโซลูชันของคุณหากเป็นไปได้

ตัวอย่าง

เพื่อความชัดเจนคำอธิบายด้านล่างใช้เครื่องหมายลบสูง ( ¯) เพื่อระบุจำนวนลบ คุณอาจส่งคืนจำนวนลบโดยใช้รูปแบบที่เหมาะสม

-5-2-3

+2+×3×2×+8 ( +2+×3×2×++2+6+8)

-14--3-1--12 ( -4--3-1---14-2-12)

+2.1+×3.5×2.2×+9.8 ( +2.1+×3.5×2.2×++2.1+7.7+9.8)

×3×÷-0-6-÷2÷×-9 ( ×3×÷-0-6-÷2÷××3×÷¯6÷2÷××3ׯ3ׯ9)

÷4÷-3-÷1÷2÷-÷1.6 ( ÷4÷-3-÷1÷2÷-÷÷4÷-3-0.5-÷÷4÷2.5÷1.6)


1
The explanations below use high minus (`¯`) to indicate negative numbers.คุณรัก APL แน่นอน
Erik the Outgolfer

@EriktheOutgolfer คุณมีข้อเสนอแนะที่ดีกว่านี้หรือไม่? นอกจากนี้ TI-BASIC ยังใช้เครื่องหมายลบสูง
อดัม

ที่จริงแล้วไม่ใช่เพราะ-s สามารถสับสนกับ-s ในขณะที่¯s ไม่สามารถสับสนกับ-s ได้
Erik the Outgolfer

Bah ฉันเพิ่งสังเกตเห็นความต้องการจำนวนจริง มากสำหรับ 290 ไบต์ของฉันจำนวนเต็มวิธีการแก้ปัญหาทางคณิตศาสตร์ Retina ...
นีล

@Neil ทำไมคุณไม่โพสต์มันเป็นคำตอบ?
Adám

คำตอบ:


4

C # (. NET Core) , 198 197 188 ไบต์

float O(string s){try{return float.Parse(s);}catch{var f=s[0];int i=s.IndexOf(f,1);float a=O(s.Substring(1,i-1)),b=O(s.Substring(i+1,s.Length-i-2));return f<43?a*b:f<44?a+b:f<46?a-b:a/b;}}

ลองออนไลน์!

การใช้งาน*และ/และ

ฟังก์ชั่นวนซ้ำ floatมันเป็นครั้งแรกพยายามที่จะแยกสายเข้าเป็น ถ้ามันล้มเหลวมันจะเรียกตัวเองซ้ำว่าเป็นตัวถูกดำเนินการครั้งแรกและครั้งที่สองจากนั้นทำการดำเนินการที่เลือกกับผลลัพธ์

  • บันทึก 1 ไบต์ต้องขอบคุณ Mr. Xcoder!
  • บันทึกไปแล้ว 9 ไบต์ด้วย TheLethalCoder!

IndefOf(f, 1)สามารถIndexOf(f,1)
Mr. Xcoder

1
ใช้floatแทนใช้รหัสถ่านเมื่อคุณมีพวกเขาอาจจะสั้นลงด้วย>และ<ในบางแห่ง
TheLethalCoder

คุณสามารถกอล์ฟไบต์ที่เปลี่ยนแปลงไปi+1,s.Length-i-2++i,s.Length+~i
Kevin Cruijssen

4

Python 3, 159 158 152 144 136 135 132 ไบต์

def t(i,a=1):
 while'-'<l[i]!='/':i+=1;a=0
 if a:l[i]='(';i=t(t(i+1));l[i-1]=')'
 return-~i
*l,=input()
t(0)
print(eval(''.join(l)))

ลองออนไลน์!

ไม่อนุญาตตัวเลขที่เป็นค่าลบ (แม้ว่าจะใช้-0-5-งานได้จริง) และต้องใช้ตัวดำเนินการของหลาม


คุณสามารถเพิ่มลิงค์ TIO ได้หรือไม่?
Adám

1
while~-(l[i]in'+-*/'):i+=1;a=1และ*l,=input()152 ไบต์
Felipe Nardi Batista

1
กับกรณีทดสอบทั้งหมด: ลิงก์
Felipe Nardi Batista


1
if a:l[i]='(';i=t(t(i+1));l[i-1]=')'ด้วยreturn-~iขนาด 135 ไบต์: P
Felipe Nardi Batista

3

เรตินา , 290 287 286 ไบต์

\d+
¦$&$*
¯¦
¯
{`\+([¯¦]1*)\+([¯¦]1*)\+
-$1-¯$2-
-(¯|¦)(1*)-([¯¦]+1*\2)-
-¯$3-¯$1$2-
(×|÷)¯(1*\1)([¯¦]1*\1)
$1¦$2¯$3
צ×[¯¦]1*×|¯¯¦?
¦
¯¦|¦¯
¯
+`-((¯|¦)1*)(1*)-\2\3-
$1
-([¯¦]1*)-[¯¦](1*)-
$1$2
צ1(1*)×([¯¦]1*)×
+צ$1×$2×+$2+
}`÷¦(?=1*÷(¯|¦)(1+)÷)(\2)*1*÷\1\2÷
$1$#3$*
((¯)|¦)(1*)
$2$.3

ลองออนไลน์! หมายเหตุ: ความสามารถในการคำนวณเลขจำนวนเต็มเท่านั้นดังนั้นกรณีทดสอบบางส่วนจึงถูกลบ ยอมรับและส่งกลับจำนวนลบโดยใช้¯คำนำหน้า แก้ไข: บันทึกแล้ว3 4 ไบต์ขอบคุณ @Cowsquack คำอธิบาย:

\d+
¦$&$*

ฉันต้องการวิธีจัดการศูนย์ดังนั้นฉันจึงใช้¦เป็นคำนำหน้าจำนวนบวก ตัวเลขจะถูกแปลงเป็น unary

¯¦
¯

แต่ตัวเลขติดลบจะต้องมี¯คำนำหน้าเท่านั้น

{`\+([¯¦]1*)\+([¯¦]1*)\+
-$1-¯$2-

การอ้างอิง+s นั้นน่าเกลียดดังนั้นฉันจึงเปลี่ยนการเติมเป็นการลบ

-(¯|¦)(1*)-([¯¦]+1*\2)-
-¯$3-¯$1$2-

หากค่าสัมบูรณ์ของ LHS ของการลบน้อยกว่า RHS ให้สลับไปรอบ ๆ และคัดค้านทั้งสองด้าน

(×|÷)¯(1*\1)([¯¦]1*\1)
$1¦$2¯$3

นอกจากนี้หาก LHS ของการคูณหรือการหารเป็นลบให้ปฏิเสธทั้งสองข้าง

צ×[¯¦]1*×|¯¯¦?
¦

นอกจากนี้หาก LHS ของการคูณเป็นศูนย์ผลลัพธ์จะเป็นศูนย์ นอกจากนี้สอง minuses ให้บวก

¯¦|¦¯
¯

แต่ลบและบวก (หรือกลับกัน) ทำลบ

+`-((¯|¦)1*)(1*)-\2\3-
$1

ลบตัวเลขสองตัวของสัญลักษณ์เดียวกัน ทำซ้ำจนกระทั่งไม่มีการลบเหลืออยู่

-([¯¦]1*)-[¯¦](1*)-
$1$2

หากยังมีการลบเครื่องหมายต้องแตกต่างกันดังนั้นให้เพิ่มตัวเลขเข้าด้วยกัน (แต่ทำได้เพียงครั้งเดียวเนื่องจากอาจเป็นการลบเครื่องหมายสองตัวที่เหมือนกันอีกครั้ง)

צ1(1*)×([¯¦]1*)×
+צ$1×$2×+$2+

ดำเนินการคูณด้วยการเพิ่มซ้ำ

}`÷¦(?=1*÷(¯|¦)(1+)÷)(\2)*1*÷\1\2÷
$1$#3$*

ดำเนินการหารจำนวนเต็ม ขั้นตอนข้างต้นอย่างใดอย่างหนึ่งจะทำให้นิพจน์ง่ายขึ้นดังนั้นวนซ้ำจนกว่าจะไม่มีการดำเนินการเหลืออยู่

((¯)|¦)(1*)
$2$.3

แปลงกลับเป็นทศนิยม


ว้าวนั่นคือ - มหากาพย์ โพสต์เรตินาที่ใหญ่ที่สุดบน PPCG? อย่างไรก็ตามโดยทั่วไปแล้วโซลูชัน QuadR และ Retina จะคล้ายกันมาก ฉันจะสร้างแรงบันดาลใจได้ไหม?
Adám

ในบรรทัดนี้+`-(([¯¦])1*)(1*)-\2\3-, [¯¦]จะกลายเป็น¯|¦
Kritixi Lithos

@ Cowquack เกิดขึ้นสามครั้งในความเป็นจริงขอบคุณ!
Neil

มีคนที่คุณพลาด([×÷]);)
Kritixi Lithos

1
@Cowsquack คุณควรที่จะไม่หาอันอื่นมิฉะนั้นฉันจะต้องตัดกัน 4 ...
Neil

2

PHP , 116 114 109 ไบต์

-5 ขอบคุณ Martin Ender

for($s=$argv[$o=1];$o!=$s;)$s=preg_replace('#([*+/-])(([\d.]+|(?R))\1(?3))\1#','($2)',$o=$s);eval("echo$s;");

ใช้*สำหรับการคูณและ/การหาร จำนวนลบเกิดขึ้นกับการทำงานแม้ว่าฉันจะไม่พยายามทำแบบนั้น

ลองออนไลน์!

Ungolfed และอธิบาย

for($s=$argv[$o=1];   # Initialize with $s = input and $o = 1;
    $o!=$s;)          # While $o != $s
    # Set $o to $s and set $s to be $s after this regex replacement:
    $s=preg_replace('#([*+/-])(([\d.]+|(?R))\1(?3))\1#','($2)',$o=$s);
    # i.e., continue to do this replacement until the result is the same on two consecutive
    # steps (no replacement was made)
# Once $o == $s (i.e. no more replacement can be made), eval the result and print
eval("echo$s;"); 

ฉันจะอธิบาย regex ด้วยเพราะมันวิเศษไปหน่อย:

([*+/-])(([\d.]+|(?R))\1(?3))\1


([*+/-])

อันดับแรกเราต้องการจับคู่ผู้ให้บริการหนึ่งในสี่รายดังต่อไปนี้: *+/-

([\d.]+|(?R))

จากนั้นเราจะต้องตรงกับทั้งจำนวนหรือการแสดงออก[\d.]+ omnifix อื่นที่ถูกต้อง(?R)

\1

จากนั้นเราจับคู่ผู้ให้บริการรายเดียวกันกับที่เป็นจุดเริ่มต้น

(?3)

จากนั้นเราก็ทำสิ่งเดียวกันกับที่เราทำในกลุ่ม 3: จับคู่ตัวเลขหรือนิพจน์ omnifix

\1

ในที่สุดให้จับคู่ตัวดำเนินการเริ่มต้นอีกครั้ง

($2)สิ่งที่ตรงนี้จะถูกแทนที่ด้วย สิ่งนี้ใช้เวลาส่วนหนึ่งในตัวดำเนินการโดยรอบและวางไว้ในวงเล็บดังนั้นมันจึงดูเหมือนสัญกรณ์มัดปกติ


2

QuadR , 33 32 27 ไบต์

-1 ขอบคุณที่วัวเถื่อน -5 ขอบคุณที่เอริก Outgolfer

((.)[\d¯\.]+){2}\2
⍎¯11↓⍵M

ด้วยอาร์กิวเมนต์ / แฟล็ก

ลองออนไลน์!

นี่เทียบเท่ากับโซลูชัน Dyalog APL ขนาด 40 ไบต์:

'((.)[\d¯\.]+){2}\2'R{⍕⍎1↓¯1↓⍵.Match}⍣≡

ลองออนไลน์!

คำอธิบาย

(ข้อความในวงเล็บหมายถึง Dyalog APL แทน QuadR)

(){2}\2 รูปแบบต่อไปนี้สองครั้งและทั้งคู่ตรงกันเช่นกัน:
  (.) อักขระใด ๆ
  [... ]+ ตามด้วยชุดอักขระต่อไปนี้หนึ่งตัวหรือมากกว่า:
   \dd igits,
   ¯ เครื่องหมายลบสูง (เครื่องหมายลบ)
   \.  ระยะเวลา

( R⎕R  ถูกวางด้วย :)

( {} ผลของฟังก์ชันนิรนามต่อไปนี้ที่ใช้กับเนมสเปซ⍵ :)

⍵M ( ⍵.Match) ข้อความของM atch
¯1↓ ปล่อยอักขระตัวสุดท้าย (สัญลักษณ์+ - ×หรือ÷)
1↓ วางอักขระตัวแรก (สัญลักษณ์)
 ดำเนินการเป็นรหัส APL
 (  stringify)

 ( ⍣≡) ทำซ้ำการแทนที่จนกว่าจะไม่มีการเปลี่ยนแปลงเกิดขึ้นอีก


ฉันคิดว่าคุณสามารถดรอป
Kritixi Lithos

@Cowsquack คุณมีสิทธิเกี่ยวกับ QuadR ⎕Rไม่สามารถทำงานกับข้อมูลตัวเลขได้ ขอบคุณ
Adám


1

Haskell , 132 ตัวอักษร

(134 ไบต์เนื่องจาก×และ÷รับสองไบต์ใน UTF-8)

f y|(n@(_:_),r)<-span(`elem`['.'..'9'])y=(read n,r)
f(c:d)|(l,_:s)<-f d,(m,_:r)<-f s=(o[c]l m,r)
o"+"=(+)
o"-"=(-)
o"×"=(*)
o"÷"=(/)

ลองออนไลน์!

fแยกวิเคราะห์อินพุตให้มากที่สุดเท่าที่จะทำได้และให้ผลลัพธ์เช่นเดียวกับสตริงที่เหลือ (ซึ่งว่างเปล่าในกรณีทดสอบ) หากไม่เป็นไปตามกฎให้ดึงสตริงส่วนที่เหลือที่ไม่สามารถแยกได้ด้วย

Haskell , 139 ตัวอักษร

...
g=fst.f

0

Perl, 64 53 ไบต์

รวม+1สำหรับ-p

perl -pe 's%([*-/])(([\d.]+|(?0))\1(?3))\1%($2)%&&redo;$_=eval' <<< "/4/-3-/1/2/-/"

ยังใช้โดยไม่ได้ตั้งใจ,(ทิ้งอาร์กิวเมนต์แรก) และบางครั้ง.(ผนวกอาร์กิวเมนต์เข้าด้วยกัน) .ใช้งานไม่ได้อย่างน่าเชื่อถือมากนักเนื่องจากมันรบกวนทศนิยมทั้งระดับการแยกวิเคราะห์และระดับการประเมินผล


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