Yapmam gereken matematik problemini söyle!


36

Öğretmenim bana her zaman ev ödevi için en karmaşık matematik problemlerini veriyor. Gibi: pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even. Ve ödevim için ne kadar zaman ayıracağımı önceden bilmek istiyorum, ama hepsini çözmek zorunda kalmak istemiyorum. Bu yüzden benim için programlamak sizin göreviniz.

Özellikler

  • Arg, stdio vb. Gibi tamamlamam gereken problemleri detaylandıran bir string alacaksınız.
  • Virgülle ayrılmış olurlar (muhtemelen comma-spaceayrılmış)
  • Sadece bir sayı biçiminde tek problemleri içerecektir (örn. 79)
  • Ve formdaki aralıklar 17-18(yine, isteğe bağlı alanlarla uğraşmanız gerekir)
  • Aralıklar, her iki ucu da içerir
  • Aralıklar, isteğe bağlı olarak oddveya evendikkate almanız gereken veya tarafından eklenir .
  • pg. 545:İsteğe bağlı boşluklarla uğraşmak zorunda kalacak şekilde, bir dizi aralık / sayfa formdaki bir sayfa numarasına göre hazırlanacaktır . Tüm sayfalardaki sorunları çözmeniz gerektiğinden, bunları güvenle göz ardı edebilirsiniz.
  • Metin büyük veya küçük harf olabilir, ancak her ikisi de olmaz.
  • Geri dönüş, stdout vb. Ödev için yapmam gereken sorunların sayısı.
  • Bu , bayt cinsinden en kısa kod kazanır!

Test Kılıfları

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
Profesör size bir dizi verebilir mi 2-4 odd? Daha basit yaklaşımlar için bazı sorunlara neden gibi görünüyor.
Björn Lindqvist

1
Şu anki sorun açıklamasına göre bunun bir test olayı olacağını düşünüyorum.
mbomb007

2
Bu test vakası olmalı:pg.492: 2-4 odd,7-9 even -> 2
mbomb007

2
Menziller üst üste binebilir mi? Örn 22-26,25-30?
Reto Koradi

1
@RetoKoradi no.
Maltysen

Yanıtlar:


15

CJam, 61 58 51 48 46 43 41 38 bayt

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

CJam tercümanındaki test durumlarını doğrulayın .

Nasıl çalışır

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.

Bu en yeni test senaryosuyla çalışıyor mu?
mbomb007

Öyle. Bağlantıya son test vakasını ekledim.
Dennis

10

Perl - 47 Bayt

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

Yeni test davasını geçmek için değiştirildi.


orijinal

Perl - 36 Bayt

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

Shebang'ı 4 olarak sayarak girdi stdin'den alınmıştır.


Örnek Kullanım

$ 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

Uyarılar

Çift / tek sıralar için, bitiş noktalarından en az birinin aralığın paritesi ile eşleşmesi beklenir. Örneğin 11-19 odd, 11-20 oddve 10-19 oddtüm doğru 5 olarak sayılır, fakat 10-20 odd6 olarak aşırı sayılır.


bu nasıl çalışıyor pg. 20: 13-15 even? ya pg. 20: 13-14 even?
Charles

1
*karakterden daha kısa olan karakter &&kolay bir iyileştirmedir:$\+=/\d+ ?-/*($'-$&>>/o|e/i)+1for@F}{
Grimmy

1
Dostum, bu akıllıca! Bir şeyi özlemediğim sürece, ortadan kaldırabilmelisin lc=~.
Dennis,

1
Parçayı anladım T^, ama bir şekilde lcdurumu değiştiren özledim $'. Prepending lciçin $'olurdu biraz daha kısa olmuştur. Bu hala her iki yaklaşım için de işe lc$'!~(T^lc$_%2)($_%2x9^lc$')!~T
Dennis

1
Önceki sürüm için @Dennis, gerekli parantez gerekli olurdu. !~Tolsa dahi, teşekkürler!
primo

6

Python 2,259 253 249 239 bayt

Burada dene

Bu muhtemelen daha çok golf oynayabilir.

Düzenleme: Madenin 2-4 evenbeklediğim gibi çalışmamasına neden olan bir hata düzeltildi . Sonra bu düzeltme için bir ayar yaptı. Bu düzeltme beni dört bayt kurtardı!

Düzenleme: Şimdi kullanımları input()ve 2 bayt kullanıcı ile giriş çevreleyen gereken iki tırnak için.

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

Daha az golf oynadı (yorumlarla!: D):

Umarım bu yorumlar bazılarına yardımcı olur. Son karmaşık çizgiyi doğru açıklayıp açıklamadığımdan hala emin değilim.

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
Küçük bir şey, Python 2 kullandığınız için, boşluk ve sekmeleri (her biri 1 byte) farklı girintiler olarak kullanabilirsiniz. İlgili ipucu
FryAmTheEggman

Ayrıca ilk önce yanlış saydığımı da tespit ettim. Sekmeleri editörlerden kopyalamak, onları boşluklara dönüştürür.
mbomb007

s=raw_input()Girinti yaparak ve çıkararak en az 4 byte tasarruf edebilirsiniz .

4

Pyth, 43 42 44 42 bayt

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

Çevrimiçi deneyin: Gösteri veya Test koşum

Sanırım hala bir ya da iki baytı doğrayabilirim.

açıklama

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                                      

Bu en yeni test senaryosuyla çalışıyor mu?
mbomb007

@ Mbomb007: Yapar.
Dennis

3

JavaScript (Spidermonkey konsolu) - 139

Komut satırında test etmek daha kolay.

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

Can [,from,to]sadece basitçe [from,to]?
Yytsi

1
@TuukkaX hayır, çünkü dizinin ilk değerini, r.execeşleşen dizenin tamamını içeren elden çıkarmak içindir .
Patrick Roberts,

3

Faktör - 488 bayt:

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

Bunu mümkün olduğunca golf oynadığımı sanmıyorum ama ilk başvuru için fena değil. Aşağıdaki yorumlanan yorum.

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

Test durumlarını çalıştırın:

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"

Kuralları nasıl okuduğumuza bağlı olarak başka bir 4 byte kaydetmek mümkün olabilir. Eğer / tuhaf her zaman küçük harf ${1,,}olarak değiştirilebilir$1


Bu en yeni test senaryosuyla çalışıyor mu?
mbomb007

Sadece test ettim ve evet.
Daniel Wakefield

1

JavaScript ( ES6 ), 149

Test etmek için Firefox'ta pasajı çalıştırın

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

Partiye biraz geç kaldığımı biliyorum, ancak bu eğlenceli bir sorun gibi görünüyordu ve C ailesi dillerini kullanan girişlerin olmaması beni rahatsız etti.

Yani burada herhangi bir regexp veya string değiştirme kullanmadan yapılan bir C ++ fonksiyonu, sadece bazı basit matematik:

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

Okunabilir olacağını söylemedim, şimdi mi? :) Üçlü operatörler cehennemdir. Biçimlendirmek için elimden geleni yaptım, ancak, umarım en azından biraz yardımcı olur.

kullanım :

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

Burada dene

Giriş tırnak içinde verilmelidir

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

Açıklama:

Genel yaklaşım mevcut girdiyi geçerli python'a dönüştürmek ve sonra bunu değerlendirmektir. Her virgülle ayrılmış değer bir diziye dönüştürülür, bunlar daha sonra hepsi birlikte eklenir ve uzunluk nihai sonucu verir.

Örneğin, girdiyle birlikte 12-15 odd,19, değerlendirmeden önce regex ikamesi aşağıdakileri üretecektir:

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

Bunu daha da bozmak için:

  • 15+1 if 15.0 else 12+1 Bu bit, bir aralık veya verilen tek bir değer olup olmadığına bağlı olarak (.
  • if x%2!="oe".find("o")Aralıktaki son haneden iki karakter uzakta bulunan değere bağlı olarak ( (?=.(.))regex'te - bunları tüketmeden iki karakter bakın), üç olası sonuç vardır:

    • x%2!="oe".find("o")olarak değerlendirilir x % 2 != 0(yalnızca tek eşleşir)
    • x%2!="oe".find("e")değerlendirir x % 2 != 1(yalnızca eşleştirilir)
    • x%2!="oe".find("[")değerlendirir x % 2 != -1(bu karakter son rakamdan sadece iki karakter uzakta olduğu için birden fazla şey olabilir, ancak tek / çift olması isteniyorsa sadece o veya e olabilir)
  • Görünüşe göre rastgele + [], virgülle ayrılmış listedeki son belirtecin son rakamdan iki karakter uzakta olmasını sağlamakla kalmıyor, aynı zamanda son '+' kelimesini kullanmak için sonuna bir şey eklememize izin veriyor Aksi takdirde iz sürüyordu.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.