บอกฉันว่าฉันต้องทำปัญหาคณิตศาสตร์มากแค่ไหน!


36

ครูของฉันให้ปัญหาคณิตศาสตร์ที่ซับซ้อนที่สุดเสมอสำหรับการบ้าน pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 evenไลค์: และฉันต้องการทราบล่วงหน้าว่าต้องใช้เวลาเท่าไรในการทำการบ้าน แต่ฉันไม่ต้องการที่จะคิดออกทั้งหมด นั่นเป็นเหตุผลที่หน้าที่ของคุณในการเขียนโปรแกรมสำหรับฉัน

ข้อมูลจำเพาะ

  • คุณจะได้รับรายละเอียดสตริงปัญหาที่ฉันต้องทำให้เสร็จเป็น args, stdio เป็นต้น
  • พวกเขาจะถูกคั่นด้วยเครื่องหมายจุลภาค (อาจถูกcomma-spaceแยกออก)
  • มันจะรวมถึงปัญหาเดียวในรูปแบบของตัวเลข (เช่น79)
  • และช่วงในรูปแบบ17-18(อีกครั้งคุณต้องจัดการกับช่องว่างที่ไม่จำเป็น)
  • ช่วงนี้รวมถึงปลายทั้งสอง
  • ช่วงที่เลือกจะถูกต่อท้ายโดยoddหรือevenที่คุณต้องคำนึงถึง
  • ชุดของช่วง / หน้าจะมีการเติมหน้าด้วยหมายเลขหน้าในแบบฟอร์มpg. 545:อีกครั้งที่ต้องจัดการกับช่องว่างที่ไม่จำเป็น คุณสามารถเพิกเฉยต่อสิ่งเหล่านี้ได้อย่างปลอดภัยเนื่องจากคุณต้องประสบปัญหากับทุกหน้า
  • ข้อความอาจเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก แต่จะไม่เป็นทั้งสองอย่าง
  • Return, stdout ฯลฯ จำนวนของปัญหาที่ฉันต้องทำเพื่อทำการบ้าน
  • ตั้งแต่นี้เป็นรหัสที่สั้นที่สุดในไบต์ชนะ!

กรณีทดสอบ

pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even   ->    27
pg. 34: 1                                                    ->    1
PG. 565: 2-5,PG.345:7                                        ->    5
pg. 343: 5,8,13 - 56 even,pg. 345: 34 - 78,80                ->    70
pg.492: 2-4 odd,7-9 even                                     ->    2

12
อาจารย์สามารถให้ช่วงของ2-4 oddคุณได้หรือไม่? ดูเหมือนจะทำให้เกิดปัญหาสำหรับแนวทางที่ง่ายกว่า
Björn Lindqvist

1
ฉันคิดว่านี่เป็นกรณีทดสอบตามคำแถลงปัญหาปัจจุบัน
mbomb007

2
ควรมีกรณีทดสอบนี้:pg.492: 2-4 odd,7-9 even -> 2
mbomb007

2
ช่วงสามารถทับซ้อนกันได้หรือไม่ เช่น22-26,25-30?
Reto Koradi

1
@RetoKoradi no.
Maltysen

คำตอบ:


15

CJam, 61 58 51 48 46 43 41 38 ไบต์

leuS-',/{':/W>:~_2*2<~z),>1f&\,5--~}%,

ตรวจสอบกรณีทดสอบในล่าม CJam

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

leuS-      e# Read a line from STDIN, convert to uppercase and remove spaces.
',/        e# Split at commas.
{          e# For each chunk:
  ':/W>    e#   Split at colons and only keep the last chunk.
  :~       e#   Evaluate the string inside the array.
  _2*      e#   Copy the array, repeated twice.
  2<       e#   Keep only the first two elements.

           e#   In all possible cases, the array now contains exactly two
           e#   integers, which are equal in case of a single problem.

  ~        e#   Dump the array on the stack.
  z),      e#   Push [0 ... -N], where N is the second integer.
  >        e#   Discard the first M elements, where M is the first integer.
  1f&      e#   Replace each element by its parity.
  \,       e#   Push L, the length of the original array.

           e#   EVEN and ODD all push elements, so L is 1 for single problems,
           e#   2 for simple ranges, 5 for odd ranges and 6 for even ranges.

  5--      e#   Discard all elements equal to L - 5 from the array of parities.

           e#   This removes 0's for odd ranges, 1's for even ranges, -3's for
           e#   other ranges and -4's for single problems, thus counting only
           e#   problems of the desired parities.

  ~        e#   Dump the resulting array on the stack.
}%         e# Collect the results in an array.
,          e# Compute its length.

ใช้งานได้กับกรณีทดสอบล่าสุดหรือไม่
mbomb007

มันทำ ฉันได้เพิ่มกรณีทดสอบล่าสุดไปที่ลิงก์
Dennis

10

Perl - 47 ไบต์

#!perl -p054
{map$\+=($_%2x9^lc$')!~T,$&..$'*/\d+ ?-/}}{

แก้ไขเพื่อผ่านกรณีทดสอบใหม่


เป็นต้นฉบับ

Perl - 36 ไบต์

#!perl -p054
$\+=/\d+ ?-/*($'-$&>>/o|e/i)+1}{

นับ shebang เป็น 4 อินพุตจะถูกนำมาจาก stdin


ตัวอย่างการใช้งาน

$ echo pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even | perl math-problems.pl
27

$ echo pg. 34: 1 | perl math-problems.pl
1

$ echo PG. 565: 2-5,PG.345:7 | perl math-problems.pl
5

$ echo pg. 343: 5,8,13 - 56 even,pg. 345: 34 - 78,80 | perl math-problems.pl
70

คำเตือน

สำหรับช่วงคู่ / คี่คาดว่าอย่างน้อยหนึ่งในจุดปลายตรงกับความเท่าเทียมกันของช่วง ตัวอย่างเช่น11-19 odd, 11-20 oddและ10-19 oddทั้งหมดจะถูกนับอย่างถูกต้องเท่าที่ 5 แต่10-20 oddจะมากกว่านับเป็น 6


มันใช้งานได้pg. 20: 13-15 evenอย่างไร หรือpg. 20: 13-14 even?
ไม่ใช่ว่า Charles

1
*สั้นกว่าตัวละครตัวหนึ่ง&&ทำให้ง่ายขึ้น:$\+=/\d+ ?-/*($'-$&>>/o|e/i)+1for@F}{
Grimmy

1
ชายนี่ฉลาด! คุณควรกำจัดlc=~ได้ถ้าฉันไม่มีอะไรหายไป
Dennis

1
ผมได้ว่าT^เป็นส่วนหนึ่ง แต่พลาดอย่างใดที่เปลี่ยนกรณีของlc $'การเตรียมพร้อมlcที่$'จะสั้นลงเล็กน้อย ที่ควรจะยังคงทำงานสำหรับวิธีการอย่างใดอย่างหนึ่ง: lc$'!~(T^lc$_%2)หรือ($_%2x9^lc$')!~T
เดนนิส

1
@Dennis สำหรับรุ่นก่อนหน้านี้จะต้องมีวงเล็บ !~Tเป็นอัจฉริยะแม้ว่าขอบคุณ!
primo

6

Python 2, 259 253 249 239 ไบต์

ลองที่นี่

นี่อาจจะยังสามารถเล่นกอล์ฟได้มากขึ้น

แก้ไข: แก้ไขข้อผิดพลาดที่ทำให้ฉันไม่ทำงาน2-4 evenอย่างที่ฉันคาดไว้ จากนั้นทำการปรับปรุงสำหรับการแก้ไขนั้น การแก้ไขนั้นช่วยฉันสี่ไบต์!

แก้ไข: ตอนนี้ใช้input()และ+2 ไบต์สำหรับเครื่องหมายคำพูดสองคำที่ผู้ใช้ต้องล้อมรอบด้วยอินพุต

import re
c=0
for x in re.sub(r'..\..*?:','',input()).replace(' ','').split(','):
 y=x.split('-')
 if len(y)<2:c+=1
 else:
    a,b=y[0],y[1];d=int(re.sub('[A-z]','',b))-int(a)+1
    if b[-1]>':':d=d/2+d%2*(int(a)%2==ord(b[-3])%2)
    c+=d
print c

หักกอล์ฟ (ด้วยความคิดเห็น!: D):

ฉันหวังว่าความคิดเห็นเหล่านี้จะช่วยได้บ้าง ฉันยังไม่แน่ใจถ้าฉันอธิบายว่าบรรทัดที่ซับซ้อนสุดท้ายถูกต้องหรือไม่

import re
def f(s):
    c=0
    l=re.sub(r'..\..*?:','',s).replace(' ','').split(',')   # remove pg #'s and split
    for x in l:
        y=x.split('-')
        if len(y)<2:                                # if not a range of numbers
            c+=1
        else:
            a,b=y[0],y[1]                           # first and second numbers in range
            d=int(re.sub('[A-z]','',b))-int(a)+1    # number of pages
            if b[-1]>':':                           # if last character is not a digit
                # half the range
                # plus 1 if odd # of pages, but only if first and last numbers in the range
                #       are the same parity
                # ord(b[-3])%2 is 0 for even (v), 1 for odd (o)
                d=d/2+(d%2)*(int(a)%2==ord(b[-3])%2)
            c+=d
    print c

2
สิ่งเล็กน้อยเนื่องจากคุณใช้ Python 2 คุณสามารถใช้ช่องว่างและแท็บ (แต่ละไบต์ 1) เป็นเยื้องที่แตกต่างกัน เคล็ดลับที่เกี่ยวข้อง
FryAmTheEggman

นอกจากนี้ยังพบว่าฉันมีความผิดนับในตอนแรก การคัดลอกแท็บจากตัวแก้ไขจะแปลงเป็นช่องว่าง
mbomb007

คุณสามารถบันทึกอย่างน้อย 4 ไบต์โดยทำs=raw_input()และลบการเยื้อง

4

Pyth, 43 42 44 42 ไบต์

lsm-%R2}hKvMc-ecd\:G\-eK?}\ed}edGYc-rzZd\,

ลองใช้งานออนไลน์: การสาธิตหรือชุดทดสอบ

ฉันคิดว่าฉันยังสามารถสับหนึ่งหรือสองไบต์

คำอธิบาย

lsm-%R2}hKvMc-ecd\:G\-eK?}\ed}edGYc-rzZd\,  implicit: z = input string
                                    rzZ     convert z to lower-case
                                   -   d    remove all spaces from z
                                  c     \,  and split by ","
  m                                         map each part d to:
               cd\:                           split d by ":"
              e                               and only use the last part (removes page number)
             -     G                          remove all letters (removes odd/even)
            c       \-                        split by "-"
          vM                                  and evaluate all (one or two) numbers
         K                                    and store the result in K
       }hK            eK                      create the list [K[0], K[0]+1, ..., K[-1]]
    %R2                                       apply modulo 2 to each element
   -                                          and remove:
                         }\ed                   "e" in d (1 for in, 0 for not in)
                        ?    }edG               if d[-1] in "abcde...z" else
                                 Y              dummy value
 s                                            combine all the lists
l                                             print the length                                      

ใช้งานได้กับกรณีทดสอบล่าสุดหรือไม่
mbomb007

@ mbomb007: ทำได้
Dennis

3

JavaScript (คอนโซล Spidermonkey) - 139

ง่ายกว่าที่จะทดสอบในบรรทัดคำสั่ง

for(r=/[:,] *(\d+)[- ]*(\d+)? *(o|e)?/gi,m=readline(z=0);f=r.exec(m);z+=!b||((p=b-a)%2||!c|a%2^/e/i.test(c))+p/(2-!c)|0)[,a,b,c]=f
print(z)

Ungolfed:

// any number set after "pg:" or a comma
// \1 is FROM, \2 is TO, \3 is odd/even 
r=/[:,] *(\d+)[- ]*(\d+)? *(o|e)?/gi;
m=readline();
z=0; // this is the sum.
while(f=r.exec(m)){
    [,from,to,oddEven]=f;
    if(!to) {
        z++;
    } else {
        if((to-from)%2) {
            // if to and from are not the same parity, add 1
            z++;
        } else {
            // if to and from are not the same parity...
            if(!oddEven) {
                // and we don't have a parity marker, add one
                z++;
            } else if(a%2 != /e/i.test(c)) {
                // if we do have a parity marker,
                // AND the parity of from and to matches the 
                // parity of the oddEven sign, then add 1
                z++;
            }
        }
        // then add the difference between to-from and
        // if oddEven exists, divide by two and round down
        z+=(to-from)/(oddEven?2:1)|0;
    }

}
print(z);

สามารถเป็น[,from,to]เพียงแค่[from,to]?
Yytsi

1
@TuukkaX ไม่ใช่เพราะนั่นคือการทิ้งค่าแรกของอาร์เรย์จากr.execซึ่งมีสตริงที่ตรงกันทั้งหมด
Patrick Roberts

3

ตัวคูณ - 488 ไบต์:

USING: arrays ascii kernel math math.parser math.ranges pcre sequences ;
IN: examples.golf.homework

: c ( a -- b )
    >lower "(?:[,:]|^) *(\\d+) *(?:- *(\\d+) *(e|o)?)?" findall [
        rest [ second dup string>number swap or ] map
        dup length 1 = [ drop 1 ] [
            dup length 2 = [ first2 swap - 1 + ] [
                first3 "o" = [ [a,b] [ odd? ] count ] [
                    [a,b] [ even? ] count
                ] if
            ] if
        ] if
    ] map sum ;

2

Bash 344 315 306 294 262 252 242 240

IFS=,
o(){ R=0;for ((i=$1;i<=$2;R+=i++%2));do :
done
}
e(){ q=$R;o $*;((R=q-R))
}
for c in ${1,,};do
c=${c#*:}
m=${c##* }
l=${c%-*}
l=${l// }
h=${c#*-}
[[ a< $m ]]&&h=${h% *}
h=${h// }
((R=h-l+1))
eval "${m::1} $l $h"
((t+=R))
done;echo $t

ฉันไม่คิดว่าฉันจะเล่นกอล์ฟให้มากที่สุดเท่าที่จะเป็นไปได้ แต่ก็ไม่เลวสำหรับการส่งครั้งแรก แสดงความคิดเห็นรุ่นด้านล่าง

IFS=, # Setup IFS for the for loops, We want to be able to split on commas

o(){ # Odd
    R=0  # Reset the R variable

    # Increments R for each odd element in the range
    # $1-$2 inclusive
    for ((i=$1;i<=$2;R+=i++%2));do
        : # Noop command
    done
}

e(){ # Even
    # Save R, it contains the total number of elements between low
    # and high
    q=$R
    # Call Odd, This will set R
    o $*
    # Set R = total number of elements in sequence - number of odd elements.
    ((R=q-R))
}

# This lowercases the firs arg. IFS causes it to split on commas.
for c in ${1,,};do
    c=${c#*:}  # Strips the page prefix if it exists
    m=${c##* }  # Capture the odd/even suffix if it exists
    l=${c%-*}  # Capture low end of a range, Strips hyphen and anything after it
    l=${l// }  # Strips spaces
    h=${c#*-}  # Capture high end of a range, Strips up to and including hyphen

    # If we have captured odd/even in m this will trigger and strip
    # it from the high range variable.
    [[ a< $m ]]&&h=${h% *}
    h=${h// }  # Strip Spaces

    # Give R a value.
    # If we are in a range it will be the number of elements in that range.
    # If we arent l and h will be equal are R will be 1
    ((R=h-l+1))

    # Call the odd or even functions if we captured one of them in m.
    # If we didnt m will contain a number and this will cause a warning
    # to stderr but it still works.
    eval "${m::1} $l $h"

    # Add R to total
    ((t+=R))
done

# Print result
echo $t

เรียกใช้กรณีทดสอบ:

bash math.sh "pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even"
bash math.sh "pg. 34: 1"
bash math.sh "PG. 565: 2-5,PG.345:7"
bash math.sh "pg. 343: 5,8,13 - 56 even,pg. 345: 34 - 78,80"
bash math.sh "pg.492: 2-4 odd,7-9 even"

ขึ้นอยู่กับวิธีที่ฉันอ่านกฎเป็นไปได้ที่จะบันทึกอีก 4 ไบต์ หากแม้ / คี่เป็นตัวพิมพ์เล็กเสมอ${1,,}สามารถเปลี่ยนเป็น$1


ใช้งานได้กับกรณีทดสอบล่าสุดหรือไม่
mbomb007

เพิ่งทดสอบแล้วและใช่
Daniel Wakefield

1

JavaScript ( ES6 ), 149

เรียกใช้ส่วนย่อยใน Firefox เพื่อทดสอบ

F=s=>s.replace(/([-,.:]) *(\d+) *(o?)(e?)/ig,(_,c,v,o,e)=>
  c=='-'?(t+=1+(o?(v-(r|1))>>1:e?(v-(-~r&~1))>>1:v-r),r=0)
  :c!='.'&&(t+=!!r,r=v)
,r=t=0)&&t+!!r

// Less golfed

U=s=>{
  var r = 0, // value, maybe range start
  t = 0; // total
  s.replace(/([-,.:]) *(\d+) *(o?)(e?)/ig, // execute function for each match
    (_ // full match, not used
     , c // separator char, match -:,.
     , v // numeric value
     , o // match first letter of ODD if present
     , e // match first letter of EVEN if present
    )=>
    {
      if (c == '-') // range end
      {
        t++; // in general, count range values as end - start + 1
        if (o) // found 'odd'
        {
          r = r | 1; // if range start is even, increment to next odd
          t += (v-r)>>1; // end - start / 2
        }
        else if (e) // found 'even'
        {
          r = (r+1) & ~1; // if range start is odd, increment to next even
          t += (v-r)>>1; // end - start / 2
        }
        else
        {
          t += v-r; // end - start
        }
        r = 0; // range start value was used
      }
      else if (c != '.') // ignore page numbers starting with '.'
      { 
        // if a range start was already saved, then it was a single value, count it
        if (r != 0) ++t;
        r = v; // save value as it counld be a range start
      }
    }
  )            
  if (r != 0) ++t; // unused, pending range start, was a single value
  return t
}

// TEST

out=x=>O.innerHTML+=x+'\n';

test=["pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even",
"pg. 34: 1", "PG. 565: 2-5,PG.345:7",
"pg. 343: 5,8,13 - 56 even,pg. 345: 34 - 78,80"];

test.forEach(t=>out(t + ' --> ' + F(t)))
<pre id=O></pre>


1

C ++ 226 224 222

ฉันรู้ว่าฉันมาสายสำหรับงานปาร์ตี้ แต่ดูเหมือนว่าจะเป็นปัญหาที่สนุกและไม่มีรายการโดยใช้ภาษาตระกูล C รบกวนฉัน

ดังนั้นนี่คือฟังก์ชัน C ++ โดยไม่ใช้การแทนที่ regexp หรือ string เพียงแค่คณิตศาสตร์ง่ายๆ:

void f(){char c;int o=0,i,j;while(cin>>c)c=='p'||c==80?cin.ignore(9,58):cin.unget(),cin>>i>>c&&c==45?cin>>j>>c&&(c=='e'||c=='o')?cin.ignore(9,44),c=='e'?i+=i&1,j+=!(j&1):(i+=!(i&1),j+=j&1),o+=(j-i)/2:o+=j-i:0,++o;cout<<o;}

Ungolfed :

void f()
{
  char c;
  int o=0,i,j;
  while(cin>>c)
    c=='p'||c==80?cin.ignore(9,58):cin.unget(),
    cin>>i>>c&&c==45?
      cin>>j>>c&&(c=='e'||c=='o')?
        cin.ignore(9,44),
        c=='e'?
          i+=i&1,j+=!(j&1)
        :(i+=!(i&1),j+=j&1),
        o+=(j-i)/2
      :o+=j-i
    :0,
    ++o;
  cout<<o;
}

ฉันไม่ได้บอกว่ามันจะอ่านได้ตอนนี้ฉัน? :) ผู้ประกอบการที่สามคือนรก ฉันพยายามจัดรูปแบบ (เรียงลำดับ) อย่างดีที่สุดดังนั้นฉันหวังว่าอย่างน้อยจะช่วยได้บ้าง

การใช้งาน :

#include <iostream>
using namespace std;

void f(){char c;int o=0,i,j;while(cin>>c)c=='p'||c==80?cin.ignore(9,58):cin.unget(),cin>>i>>c&&c==45?cin>>j>>c&&(c=='e'||c=='o')?cin.ignore(9,44),c=='e'?i+=i&1,j+=!(j&1):(i+=!(i&1),j+=j&1),o+=(j-i)/2:o+=j-i:0,++o;cout<<o;}

int main()
{
  f();
}


0

Python 2 - 163 ไบต์:

ลองที่นี่

ต้องป้อนข้อมูลภายในเครื่องหมายคำพูด

import re
print len(eval(re.sub('([^,]+:|) *(\d+) *-? *(\d*)(?=.(.)).*?,',r'[x for x in range(\2,\3+1 if \3.0 else \2+1)if x%2!="oe".find("\4")]+',input()+',[]')))

คำอธิบาย:

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

ตัวอย่างเช่นกับอินพุต12-15 odd,19ก่อนการประเมินผลการทดแทน regex จะสร้าง:

[x for x in range(12,15+1 if 15.0 else 12+1)if x%2!="oe".find("o")]
+[x for x in range(19,+1 if .0 else 19+1)if x%2!="oe".find("[")]
+[]

หากต้องการทำลายสิ่งนี้ให้มากขึ้น:

  • 15+1 if 15.0 else 12+1 บิตนี้จะทำให้แน่ใจว่าอาร์กิวเมนต์ที่สองของช่วง () ถูกต้องขึ้นอยู่กับว่ามีช่วงหรือค่าเดียวที่กำหนด (ถ้า \ 3 ว่างเปล่า \ 3.0 จะประเมินเป็นเท็จ)
  • if x%2!="oe".find("o")ขึ้นอยู่กับค่าที่พบสองตัวละครห่างจากตัวเลขสุดท้ายในช่วง ( (?=.(.))ใน regex - lookahead ตัวละครสองตัวโดยไม่ต้องใช้พวกเขา) มีผลลัพธ์ที่เป็นไปได้สามประการ:

    • x%2!="oe".find("o")ประเมินเป็นx % 2 != 0(จับคู่คี่เท่านั้น)
    • x%2!="oe".find("e")ประเมินถึงx % 2 != 1(จับคู่คู่เท่านั้น)
    • x%2!="oe".find("[")ประเมินเป็นx % 2 != -1(ตัวละครนี้อาจมีหลายสิ่งเพราะมันเป็นเพียงแค่ตัวละครสองตัวที่อยู่ห่างจากตัวเลขสุดท้าย แต่จะมีค่าเป็น o หรือ e เท่านั้นหากคี่ / คู่มีเจตนา)
  • การสุ่ม + [] ที่ดูเหมือนว่าท้ายที่สุดคือเพื่อให้แน่ใจว่าโทเค็นสุดท้ายในรายการที่คั่นด้วยเครื่องหมายจุลภาคมีอักขระสองตัวห่างจากหลักสุดท้าย แต่ยังช่วยให้เราสามารถผนวกบางสิ่งจนถึงที่สุดเพื่อใช้ '+' ล่าสุด ซึ่งจะได้รับการติดตามเป็นอย่างอื่น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.