Katakan berapa banyak masalah matematika yang harus saya lakukan!


36

Guru saya selalu memberi saya satu set masalah matematika yang paling rumit untuk pekerjaan rumah. Seperti: pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even. Dan saya ingin tahu sebelumnya berapa banyak waktu yang harus saya sisihkan untuk pekerjaan rumah saya, tetapi saya tidak ingin harus mencari tahu semua itu. Itu sebabnya tugas Anda untuk memprogramnya untuk saya.

Spesifikasi

  • Anda akan mendapatkan string yang merinci masalah yang harus saya selesaikan sebagai args, stdio, dll.
  • Mereka akan dipisahkan koma (mungkin comma-spacedipisahkan)
  • Ini akan mencakup masalah tunggal dalam bentuk hanya angka (misalnya 79)
  • Dan rentang dalam bentuk 17-18(sekali lagi, Anda harus berurusan dengan ruang opsional)
  • Rentang ini termasuk kedua ujungnya
  • Rentang opsional akan diakhiri dengan oddatau even, yang harus Anda perhitungkan.
  • Satu set rentang / halaman akan didahului dengan nomor halaman dalam formulir pg. 545:, sekali lagi harus berurusan dengan spasi opsional. Anda dapat mengabaikan ini dengan aman, karena Anda perlu mendapatkan masalah di semua halaman
  • Teks mungkin dalam huruf besar atau kecil, tetapi tidak akan keduanya.
  • Kembali, stdout, dll. Sejumlah masalah yang harus saya lakukan untuk pekerjaan rumah.
  • Karena ini adalah , kode terpendek dalam byte menang!

Uji Kasus

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
Bisakah profesor memberi Anda sejumlah 2-4 odd? Tampaknya menyebabkan beberapa masalah untuk pendekatan yang lebih sederhana.
Björn Lindqvist

1
^ Saya pikir ini harus menjadi ujian, sesuai dengan pernyataan masalah saat ini.
mbomb007

2
Seharusnya ada test case ini:pg.492: 2-4 odd,7-9 even -> 2
mbomb007

2
Bisakah rentang tumpang tindih? Misalnya 22-26,25-30?
Reto Koradi

1
@RetoKoradi no.
Maltysen

Jawaban:


15

CJam, 61 58 51 48 46 43 41 38 byte

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

Verifikasi kasus uji dalam juru bahasa CJam .

Bagaimana itu bekerja

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.

Apakah ini bekerja dengan test case terbaru?
mbomb007

Itu benar. Saya telah menambahkan test case terbaru ke tautan.
Dennis

10

Perl - 47 Bytes

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

Diubah untuk lulus uji kasus baru.


Asli

Perl - 36 Bytes

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

Menghitung shebang sebagai 4, input diambil dari stdin.


Contoh Penggunaan

$ 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

Peringatan

Untuk rentang genap / ganjil, diharapkan setidaknya satu titik akhir cocok dengan paritas rentang. Sebagai contoh, 11-19 odd, 11-20 odd, dan 10-19 oddsemua akan benar dihitung sebagai 5, tapi 10-20 oddakan lebih-dihitung sebagai 6.


bagaimana cara kerjanya pg. 20: 13-15 even? atau pg. 20: 13-14 even?
Bukannya Charles

1
*adalah satu karakter lebih pendek dari &&, membuat peningkatan yang mudah:$\+=/\d+ ?-/*($'-$&>>/o|e/i)+1for@F}{
Grimmy

1
Sobat, ini pintar! Kecuali saya kehilangan sesuatu, Anda harus bisa menghilangkannya lc=~.
Dennis

1
Saya mendapatkan T^bagian itu, tetapi entah bagaimana melewatkan itu lcmengubah kasus $'. Bertambah lcke $'akan sedikit lebih pendek. Itu masih harus bekerja untuk kedua pendekatan: lc$'!~(T^lc$_%2)atau($_%2x9^lc$')!~T
Dennis

1
@ Dennis untuk versi sebelumnya, itu akan membutuhkan tanda kurung. !~Tjenius, terima kasih!
Primo

6

Python 2, 259 253 249 239 byte

Coba di sini

Ini mungkin masih bisa lebih banyak golf.

Sunting: Memperbaiki bug yang menyebabkan pekerjaan saya tidak berfungsi 2-4 evenseperti yang saya harapkan. Kemudian buat penyesuaian untuk perbaikan itu. Perbaikan itu menyelamatkan saya empat byte!

Sunting: Sekarang menggunakan input()dan +2 byte untuk dua tanda kutip yang harus dikelilingi input oleh pengguna.

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

Kurang bermain golf (dengan komentar!: D):

Saya harap komentar ini membantu. Saya masih tidak yakin apakah saya menjelaskan garis kompleks terakhir dengan benar atau tidak.

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
Hanya sedikit, karena Anda menggunakan Python 2, Anda dapat menggunakan spasi dan tab (masing-masing 1 byte) sebagai indentasi yang berbeda. Kiat terkait
FryAmTheEggman

Juga menemukan saya salah menghitung pada awalnya. Menyalin tab dari editor mengubahnya menjadi spasi.
mbomb007

Anda dapat menyimpan setidaknya 4 byte dengan melakukan s=raw_input()dan menghapus beberapa indentasi.

4

Pyth, 43 42 44 42 byte

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

Cobalah secara online: Demonstrasi atau Uji harness

Saya pikir saya masih bisa memotong satu atau dua byte.

Penjelasan

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                                      

Apakah ini bekerja dengan test case terbaru?
mbomb007

@ mbomb007: Ya.
Dennis

3

JavaScript (Konsol Spidermonkey) - 139

Hanya lebih mudah untuk menguji pada baris perintah.

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)

Tidak Disatukan:

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

Bisakah [,from,to]begitu saja [from,to]?
Yytsi

1
@ TuukkaX tidak karena itu adalah untuk membuang nilai pertama dari array r.exec, yang berisi seluruh string yang cocok.
Patrick Roberts

3

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

Saya tidak berpikir saya telah bermain golf ini sebanyak mungkin tetapi tidak buruk untuk pengiriman pertama. Versi yang dikomentari di bawah ini.

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

Jalankan uji kasus:

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"

Bergantung pada bagaimana saya membaca aturan itu, dimungkinkan untuk menyimpan 4 byte lagi. Jika genap / ganjil selalu huruf kecil ${1,,}dapat diubah menjadi$1


Apakah ini bekerja dengan test case terbaru?
mbomb007

Hanya mengujinya dan ya.
Daniel Wakefield

1

JavaScript ( ES6 ), 149

Jalankan cuplikan di Firefox untuk menguji

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

Saya tahu saya agak terlambat ke pesta, tapi ini sepertinya masalah yang menyenangkan dan kurangnya entri menggunakan bahasa C-family mengganggu saya.

Jadi, inilah fungsi C ++ yang tidak menggunakan regexp atau substitusi string, hanya beberapa matematika sederhana:

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

Tidak Disatukan :

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

Saya tidak mengatakan itu akan dapat dibaca, bukan? :) Operator ternary adalah neraka. Saya mencoba yang terbaik untuk (semacam) memformatnya, jadi saya harap ini membantu setidaknya sedikit.

Penggunaan :

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

Coba di sini

Masukan harus diberikan di dalam tanda kutip

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

Penjelasan:

Pendekatan umum adalah mengubah input yang ada menjadi python yang valid, kemudian mengevaluasi ini. Setiap nilai yang dipisahkan koma dikonversi ke array, yang kemudian semuanya ditambahkan bersamaan dan panjangnya memberikan hasil akhir.

Misalnya, dengan input 12-15 odd,19, sebelum evaluasi substitusi regex akan menghasilkan:

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

Untuk memecah ini lebih lanjut:

  • 15+1 if 15.0 else 12+1 Bit ini akan memastikan argumen kedua range () benar tergantung apakah ada range atau nilai tunggal yang diberikan (jika \ 3 kosong, \ 3.0 akan dievaluasi menjadi false).
  • if x%2!="oe".find("o")Bergantung pada nilai yang ditemukan dua karakter dari digit terakhir dalam rentang ( (?=.(.))di regex - lihat dua karakter tanpa mengkonsumsinya), ada tiga kemungkinan hasil:

    • x%2!="oe".find("o")mengevaluasi ke x % 2 != 0(hanya ganjil yang cocok)
    • x%2!="oe".find("e")mengevaluasi hingga x % 2 != 1(hanya genap cocok)
    • x%2!="oe".find("[")mengevaluasi ke x % 2 != -1(karakter ini bisa beberapa hal karena hanya dua karakter dari digit terakhir, tetapi hanya akan menjadi o atau e jika ganjil / genap dimaksudkan)
  • + [] Yang kelihatannya acak di akhir adalah untuk memastikan bahwa token terakhir dalam daftar yang dipisahkan koma memiliki karakter dua dari digit terakhir, tetapi juga memungkinkan kita untuk menambahkan sesuatu sampai akhir untuk menggunakan '+' yang terakhir. yang akan tertinggal sebaliknya.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.