Cho tôi biết có bao nhiêu bài toán tôi phải làm!


36

Giáo viên của tôi luôn đưa cho tôi các bài toán phức tạp nhất cho bài tập về nhà. Giống như : pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even. Và tôi muốn biết trước bao nhiêu thời gian để dành cho bài tập về nhà của mình, nhưng tôi không muốn phải tìm ra tất cả. Đó là lý do tại sao nhiệm vụ của bạn là lập trình nó cho tôi.

Thông số kỹ thuật

  • Bạn sẽ nhận được một chuỗi chi tiết các vấn đề mà tôi phải hoàn thành như args, stdio, v.v.
  • Chúng sẽ được phân tách bằng dấu phẩy (có thể comma-spacetách ra)
  • Nó sẽ bao gồm các vấn đề duy nhất ở dạng chỉ một số (ví dụ 79)
  • Và phạm vi trong biểu mẫu 17-18(một lần nữa, bạn phải xử lý các không gian tùy chọn)
  • Phạm vi bao gồm cả hai đầu
  • Các phạm vi sẽ tùy ý được thêm vào bởi oddhoặc even, mà bạn phải tính đến.
  • Một tập hợp các phạm vi / trang sẽ được thêm vào bởi một số trang trong biểu mẫu pg. 545:, một lần nữa phải xử lý các khoảng trắng tùy chọn. Bạn có thể yên tâm bỏ qua những điều này, vì bạn cần phải giải quyết vấn đề trên tất cả các trang
  • Văn bản có thể viết hoa hoặc viết thường, nhưng sẽ không phải là cả hai.
  • Trả lại, stdout, vv số lượng các vấn đề tôi phải làm cho bài tập về nhà.
  • Vì đây là , mã ngắn nhất tính bằng byte sẽ thắng!

Các trường hợp thử nghiệm

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
Giáo sư có thể cung cấp cho bạn một phạm vi 2-4 odd? Nó xuất hiện để gây ra một số vấn đề cho các phương pháp đơn giản hơn.
Bjorn Lindqvist

1
^ Tôi nghĩ rằng đây nên là một trường hợp thử nghiệm, theo tuyên bố vấn đề hiện tại.
mbomb007

2
Cần có trường hợp thử nghiệm này:pg.492: 2-4 odd,7-9 even -> 2
mbomb007

2
Các phạm vi có thể chồng lấp? Ví dụ 22-26,25-30?
Reto Koradi

1
@RetoKoradi không.
Maltysen

Câu trả lời:


15

CJam, 61 58 51 48 46 43 41 38 byte

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

Xác nhận các trường hợp thử nghiệm trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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.

Điều này có làm việc với trường hợp thử nghiệm mới nhất?
mbomb007

Nó làm. Tôi đã thêm trường hợp thử nghiệm mới nhất vào liên kết.
Dennis

10

Perl - 47 byte

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

Sửa đổi để vượt qua trường hợp thử nghiệm mới.


Nguyên

Perl - 36 byte

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

Đếm shebang là 4, đầu vào được lấy từ stdin.


Sử dụng mẫu

$ 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

Hãy cẩn thận

Đối với phạm vi chẵn / lẻ, dự kiến ​​ít nhất một trong các điểm cuối khớp với tính chẵn lẻ của phạm vi. Ví dụ, 11-19 odd, 11-20 odd, và 10-19 oddtất cả sẽ được tính một cách chính xác nhất là 5, nhưng 10-20 oddsẽ là quá tính là 6.


cái này hoạt động pg. 20: 13-15 eventhế nào hay pg. 20: 13-14 even?
Không phải là Charles

1
*ngắn hơn một ký tự &&, giúp cải thiện dễ dàng:$\+=/\d+ ?-/*($'-$&>>/o|e/i)+1for@F}{
Grimmy

1
Man, đây là thông minh! Trừ khi tôi thiếu một cái gì đó, bạn sẽ có thể loại bỏ lc=~.
Dennis

1
Tôi đã nhận T^phần đó, nhưng bằng cách nào đó đã bỏ lỡ điều đó lcđã thay đổi trường hợp $'. Chuẩn lcbị $'sẽ có một chút ngắn hơn. Điều đó vẫn sẽ hiệu quả đối với một trong hai cách tiếp cận: lc$'!~(T^lc$_%2)hoặc($_%2x9^lc$')!~T
Dennis

1
@Dennis cho phiên bản trước, nó sẽ có dấu ngoặc đơn yêu cầu. !~Tlà thiên tài mặc dù, cảm ơn!
primo

6

Python 2, 259 253 249 239 byte

Hãy thử nó ở đây

Điều này có lẽ vẫn có thể được chơi golf nhiều hơn.

Chỉnh sửa: Đã sửa lỗi khiến tôi không hoạt động 2-4 evennhư tôi mong đợi. Sau đó thực hiện một điều chỉnh cho sửa chữa đó. Sửa chữa đó đã tiết kiệm cho tôi bốn byte!

Chỉnh sửa: Bây giờ sử dụng input()+2 byte cho hai dấu ngoặc kép mà người dùng phải bao quanh đầu vào.

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

Ít chơi gôn hơn (có ý kiến ​​!: D):

Tôi hy vọng những ý kiến ​​này sẽ giúp một số. Tôi vẫn không chắc chắn nếu tôi giải thích chính xác dòng phức tạp cuối cùng hay không.

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
Chỉ cần một điều nhỏ, vì bạn đang sử dụng Python 2, bạn có thể sử dụng khoảng trắng và tab (mỗi byte 1 byte) làm các thụt lề khác nhau. Mẹo có liên quan
FryAmTheEggman

Cũng tìm thấy tôi đã đếm sai lúc đầu. Sao chép các tab từ các biên tập viên chuyển đổi chúng thành không gian.
mbomb007

Bạn có thể lưu ít nhất 4 byte bằng cách thực hiện s=raw_input()và loại bỏ một số vết lõm.

4

Pyth, 43 42 44 42 byte

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

Dùng thử trực tuyến: Trình diễn hoặc thử nghiệm khai thác

Tôi nghĩ rằng tôi vẫn có thể cắt một hoặc hai byte.

Giải trình

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                                      

Điều này có làm việc với trường hợp thử nghiệm mới nhất?
mbomb007

@ mbomb007: Nó có.
Dennis

3

JavaScript (Bảng điều khiển Spidermonkey) - 139

Nó chỉ dễ dàng hơn để kiểm tra trên dòng lệnh.

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)

Ung dung:

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

Có thể [,from,to]chỉ đơn giản là [from,to]?
Yytsi

1
@TuukkaX không vì đó là loại bỏ giá trị đầu tiên của mảng r.exec, chứa toàn bộ chuỗi khớp.
Patrick Roberts

3

Yếu tố - 488 byte:

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

Tôi không nghĩ rằng tôi đã chơi golf nhiều nhất có thể nhưng không tệ cho lần gửi đầu tiên. Phiên bản bình luận dưới đây.

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

Chạy các trường hợp thử nghiệm:

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"

Tùy thuộc vào cách tôi đọc các quy tắc, có thể lưu thêm 4 byte. Nếu chẵn / lẻ luôn là chữ thường ${1,,}có thể thay đổi thành$1


Điều này có làm việc với trường hợp thử nghiệm mới nhất?
mbomb007

Chỉ cần thử nghiệm và có nó làm.
Daniel Wakefield

1

JavaScript ( ES6 ), 149

Chạy đoạn trích trong Firefox để kiểm tra

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

Tôi biết tôi đến dự tiệc muộn, nhưng đây có vẻ là một vấn đề thú vị và thiếu các mục sử dụng ngôn ngữ gia đình C làm phiền tôi.

Vì vậy, đây là một hàm C ++ không sử dụng thay thế chuỗi hoặc khai thác chuỗi, chỉ là một số phép toán đơn giản:

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

Ung dung :

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

Tôi đã không nói rằng nó sẽ có thể đọc được, bây giờ phải không? :) Toán tử ternary là địa ngục. Mặc dù vậy, tôi đã cố gắng hết sức để (định dạng) định dạng nó, vì vậy tôi hy vọng nó sẽ giúp ít nhất một chút.

Cách sử dụng :

#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 byte:

Hãy thử nó ở đây

Đầu vào phải được đưa ra bên trong dấu ngoặc kép

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()+',[]')))

Giải trình:

Cách tiếp cận chung là chuyển đổi đầu vào hiện có thành python hợp lệ, sau đó đánh giá điều này. Mỗi giá trị được phân tách bằng dấu phẩy được chuyển đổi thành một mảng, sau đó tất cả được nối lại với nhau và độ dài cho kết quả cuối cùng.

Ví dụ, với đầu vào 12-15 odd,19, trước khi đánh giá, sự thay thế regex sẽ tạo ra:

[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("[")]
+[]

Để phá vỡ điều này hơn nữa:

  • 15+1 if 15.0 else 12+1 Bit này sẽ đảm bảo đối số thứ hai của phạm vi () là chính xác tùy thuộc vào việc có một phạm vi hoặc một giá trị nào đó được đưa ra (nếu \ 3 trống, \ 3.0 sẽ đánh giá thành sai).
  • if x%2!="oe".find("o")Tùy thuộc vào giá trị tìm thấy hai ký tự cách chữ số cuối cùng trong phạm vi ( (?=.(.))trong biểu thức chính quy - nhìn hai ký tự mà không tiêu thụ chúng), có ba kết quả có thể xảy ra:

    • x%2!="oe".find("o")ước tính x % 2 != 0(chỉ khớp lẻ)
    • x%2!="oe".find("e")đánh giá x % 2 != 1(thậm chí chỉ khớp)
    • x%2!="oe".find("[")ước tính x % 2 != -1(ký tự này có thể là nhiều thứ vì nó chỉ cách hai chữ số cuối cùng, nhưng sẽ chỉ là o hoặc e nếu có ý định lẻ / chẵn)
  • Dường như ngẫu nhiên + [] ở cuối là để đảm bảo rằng mã thông báo cuối cùng trong danh sách được phân tách bằng dấu phẩy có một ký tự cách hai chữ số cuối cùng, nhưng cũng cho phép chúng ta thêm thứ gì đó vào cuối để sử dụng cuối '+' mà đã được theo dõi khác.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.