การลดงบคณิตศาสตร์


18

ความท้าทาย

คุณเป็นเจ้าของบริการที่น่าอัศจรรย์ที่เรียกว่าCoyote Betaซึ่งตอบคำถามคณิตศาสตร์ที่ผู้ใช้ส่งไปยังอินเทอร์เน็ตได้อย่างน่าอัศจรรย์

แต่ปรากฎว่าแบนด์วิดท์มีราคาแพง คุณมีสองทางเลือกคือสร้าง " Coyote Beta Pro" หรือหาวิธีแก้ปัญหานี้ (x + 2)เพิ่งมีคนสอบถาม ลูกค้าไม่สามารถส่งx+2และผู้ใช้จะไม่เห็นความแตกต่าง?

งาน

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

ผู้ประกอบการเพียงให้ที่นี่เป็น+, -, *, /และ^(ยกกำลัง) โดยมีการเชื่อมโยงกันทางคณิตศาสตร์ที่ได้มาตรฐานและมีความสำคัญ ช่องว่างเฉพาะที่ระบุในอินพุตจะเป็นอักขระช่องว่างจริง

ตัวอย่างอินพุต / เอาต์พุต

Input       | Output
------------|--------------
(2+x) + 3   | 2+x+3
((4+5))*x   | (4+5)*x
z^(x+42)    | z^(x+42)
x - ((y)+2) | x-(y+2)
(z - y) - x | z-y-x
x^(y^2)     | x^y^2
x^2 / z     | x^2/z
- (x + 5)+3 | -(x+5)+3

เกณฑ์การให้คะแนน

อินพุต / เอาต์พุตสามารถใช้วิธีการที่ต้องการ โปรแกรมที่เล็กที่สุดเป็นไบต์ชนะ

บิตที่แน่นอน

การยกกำลังนั้นมีความสัมพันธ์ที่ถูกต้องและเป็นไปตามความสำคัญทางคณิตศาสตร์มาตรฐาน (สูงสุด) ตัวอักษรเป็นตัวเลขที่ถูกต้องและแท้จริงตัวแปรที่ถูกต้อง/[0-9]+/ /[a-z]+/ตัวอักษรตัวแปรเดียวหมายถึงค่าเดียวแม้ว่าความยาวอักขระจะยาวกว่า 1

สิ่งที่มีความหมายโดย "วงเล็บรอบการดำเนินการเชื่อมโยงไม่จำเป็นต้องเก็บรักษาไว้" คือผลลัพธ์ที่ควรประกอบด้วยการแสดงออกที่ทำให้ต้นไม้แยกวิเคราะห์เหมือนกันยกเว้นว่าการดำเนินการเชื่อมโยงสามารถจัดใหม่ได้


แนวคิดคือการสร้างคำสั่งที่เทียบเท่ากันน้อยที่สุดซึ่งส่งผลให้แผนภูมิแยกวิเคราะห์เดียวกัน นี่คือเพื่อให้โคโยตี้เบต้าสามารถแสดงให้เห็นได้เมื่อผู้ใช้สร้างแบบสอบถาม
TND

หากตัวแปรที่ถูกต้องคือ/[a-z]+/หมายความว่าabไม่อนุญาตการคูณด้วยการตีข่าวเช่น?
Joe Z.

1
คุณต้องการ2+(3+4)ที่จะเปลี่ยนเป็น2+3+4ใช่มั้ย สิ่งนี้จะเปลี่ยนแผนผังการแยกวิเคราะห์
feersum

2
ฉันมีปัญหากับการอ้างสิทธิ์x^(y/2)=x^y/2นั้น การยกกำลังมีลำดับความสำคัญสูงกว่าคือเออร์x^y/2=(x^y)/2โก
Conor O'Brien

1
Aww man ฉันกำลังจะส่งเป็นPrompt X:expr(X)TI-BASIC แต่คุณไม่สามารถทำให้เป็นเรื่องง่าย :(
DankMemes

คำตอบ:


1

C #, 523 519 504 ไบต์

ตรวจสอบความคิดเห็นในรหัสเพื่อดูว่ามันทำงานอย่างไร!


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

using System;using System.Collections.Generic;namespace n{class p{static void Main(string[]a){foreach(String s in a){String r=s.Replace(" ","");List<int>l=new List<int>();for(int i=0;i<r.Length;i++){if(r[i]=='('){l.Add(i);continue;}if(r[i]==')'){switch(r[Math.Max(l[l.Count-1]-1,0)]){case'+':case'(':switch(r[Math.Min(i+1,r.Length-1)]){case'+':case'-':case')':r=r.Remove(Math.Max(l[l.Count-1],0),1);r=r.Remove(Math.Min(i,r.Length)-1,1);i-=2;break;}break;}l.RemoveAt(l.Count-1);}}Console.WriteLine(r);}}}}

Ungolfed

using System;
using System.Collections.Generic;

namespace n {
    class p {
        static void Main( string[] a ) {
            // Loop every String given for the program
            foreach (String s in a) {
                // Get rid of the spaces
                String r = s.Replace( " ", "" );

                // A little helper that will have the indexes of the '('
                List<int> l = new List<int>();

                // Begin the optimizatio process
                for (int i = 0; i < r.Length; i++) {
                    // If char is an '(', add the index to the helper list and continue
                    if (r[ i ] == '(') {
                        l.Add( i );
                        continue;
                    }

                    // If the char is an ')', validate the group
                    if (r[ i ] == ')') {
                        // If the char before the last '(' is an '+' or '(' ...
                        switch (r[ Math.Max( l[ l.Count - 1 ] - 1, 0 ) ]) {
                            case '+':
                            case '(':
                                // ... and the char after the ')' we're checking now is an '+', '-' or ')' ...
                                switch (r[ Math.Min( i + 1, r.Length - 1 ) ]) {
                                    case '+':
                                    case '-':
                                    case ')':
                                        // Remove the '()' since they're most likely desnecessary.
                                        r = r.Remove( Math.Max( l[ l.Count - 1 ], 0 ), 1 );
                                        r = r.Remove( Math.Min( i, r.Length ) - 1, 1 );

                                        // Go two steps back in the loop since we removed 2 chars from the String,
                                        //   otherwise we would miss some invalid inputs
                                        i -= 2;
                                        break;
                                }

                                break;
                        }

                        // Remove the last inserted index of '(' from the list,
                        //   since we matched an ')' for it.
                        l.RemoveAt( l.Count - 1 );
                    }
                }

                // Print the result
                Console.WriteLine( r );
            }
        }
    }
}

หมายเหตุด้านข้าง

  1. แก้ไขข้อผิดพลาดบางอย่างและเปลี่ยนชื่อบาง vars
  2. ซ้อนสวิตช์เพื่อกำจัดตัวแปรที่ไม่จำเป็น นอกจากนี้ยังแก้ไขข้อบกพร่องที่จะทำให้แก้ปัญหาบางอย่างที่ไม่ถูกต้องรายงานโดยAnders Kaseorg

PS:หากคุณมีเคล็ดลับหรือพบข้อผิดพลาดโปรดแจ้งให้เราทราบในความคิดเห็นและฉันจะพยายามแก้ไข (ฉันจะเพิ่มบันทึกเกี่ยวกับการแก้ไขข้อบกพร่องด้วยชื่อของคุณ;))


คำตอบที่ดี! : D คำตอบมากมายที่นี่มักจะได้รับที่ดีกว่าถ้าคุณมีคำอธิบาย: P
cat

ฉันสามารถทำได้ในรูปแบบของการแสดงความคิดเห็นรหัส?
auhmaan

แน่นอนว่าอะไรก็ตามที่ใช้ได้ c:
cat

งั้นฉันจะทำอย่างนั้น! ฉันจะพยายามเพิ่มบทสรุปที่ใดที่หนึ่งด้วย
auhmaan

ยินดีต้อนรับสู่การเขียนโปรแกรมปริศนาและรหัสกอล์ฟโดยวิธี! (แม้ว่าไม่ใช่คำตอบแรกของคุณ)
cat

0

C ++, 284 ไบต์

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

#include<iostream>
#include<algorithm>
int main(){std::string e;std::getline(std::cin,e);e.erase(std::remove_if(e.begin(),e.end(),isspace),e.end());for(int x=0;x<e.length();x++){if(e[x]=='('&&e[x+1]=='('){e.erase(x,1);}if(e[x]==')'&&e[x+1]==')'){e.erase(x,1);}}std::cout<<e;return 0;}

Ungolfed

#include<iostream>
#include<algorithm>

int main()
{
    std::string e;
    std::getline(std::cin, e);
    e.erase(std::remove_if(e.begin(), e.end(), isspace), e.end());
    for(int x = 0; x < e.length(); x++) {
        if (e[x] == '(' && e[x+1] == '('){
            e.erase(x, 1);
        }
        if (e[x] == ')' && e[x+1] == ')'){
            e.erase(x, 1);
        }
    }
    std::cout<<e;
    return 0;
}

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