Sagen Sie mir, wie viele mathematische Probleme ich machen muss!


36

Mein Lehrer gibt mir immer die kompliziertesten mathematischen Aufgaben für die Hausaufgaben. Wie: pg. 546: 17-19, 22, 26, pg. 548: 35-67 odd, 79, 80-86 even. Und ich möchte im Voraus wissen, wie viel Zeit für meine Hausaufgaben zur Verfügung steht, aber ich möchte nicht alles herausfinden müssen. Deshalb ist es deine Aufgabe, es für mich zu programmieren.

Spezifikationen

  • Sie erhalten eine Zeichenfolge, in der die Probleme aufgeführt sind, die ich als args, stdio usw. ausführen muss.
  • Sie werden durch Kommas getrennt (möglicherweise comma-spacegetrennt)
  • Es wird einzelne Probleme in Form von nur einer Zahl enthalten (zB 79)
  • Und Bereiche in der Form 17-18(wieder müssen Sie mit optionalen Leerzeichen umgehen)
  • Die Bereiche umfassen beide Enden
  • Die Bereiche werden optional mit oddoder angefügt even, was Sie berücksichtigen müssen.
  • Einer Reihe von Bereichen / Seiten wird im Formular eine Seitennummer vorangestellt pg. 545:, die wiederum optionale Leerzeichen enthält. Sie können diese ignorieren, da Sie die Probleme auf allen Seiten beheben müssen
  • Der Text kann in Groß- oder Kleinbuchstaben geschrieben sein, jedoch nicht in beiden.
  • Geben Sie an, wie viele Probleme ich bei den Hausaufgaben habe.
  • Da es sich um , kürzesten Code in Bytes gewinnt!

Testfälle

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
Kann der Professor Ihnen eine Auswahl geben 2-4 odd? Es scheint einige Probleme für einfachere Ansätze zu verursachen.
Björn Lindqvist,

1
^ Ich denke das sollte ein Testfall sein, nach der aktuellen Problemstellung.
mbomb007

2
Es sollte diesen Testfall geben:pg.492: 2-4 odd,7-9 even -> 2
mbomb007

2
Können sich die Bereiche überschneiden? ZB 22-26,25-30?
Reto Koradi

1
@RetoKoradi Nr.
Maltysen

Antworten:


15

CJam, 61 58 51 48 46 43 41 38 Bytes

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

Überprüfen Sie die Testfälle im CJam-Interpreter .

Wie es funktioniert

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.

Funktioniert das mit dem neuesten Testfall?
mbomb007,

Es tut. Ich habe den Link um den neuesten Testfall erweitert.
Dennis

10

Perl - 47 Bytes

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

Geändert, um den neuen Testfall zu bestehen.


Original

Perl - 36 Bytes

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

Zählt man den Shebang als 4, wird die Eingabe von stdin übernommen.


Beispielnutzung

$ 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

Vorbehalte

Für gerade / ungerade Bereiche wird erwartet, dass mindestens einer der Endpunkte mit der Parität des Bereichs übereinstimmt. Zum Beispiel 11-19 odd, 11-20 oddund 10-19 oddalle korrekt als 5 gezählt werden, sondern 10-20 oddwird als 6 über gezählt sein.


wie funktioniert das für pg. 20: 13-15 even? oder pg. 20: 13-14 even?
Nicht dass Charles

1
*ist ein Zeichen kürzer als &&, was für eine leichte Verbesserung $\+=/\d+ ?-/*($'-$&>>/o|e/i)+1for@F}{
sorgt

1
Mann, das ist schlau! Sofern ich nichts vermisse, sollten Sie in der Lage sein, zu beseitigen lc=~.
Dennis

1
Ich habe das T^Teil verstanden, aber irgendwie übersehen, dass lcsich der Fall geändert hat $'. Die Vorbereitung lcauf $'wäre etwas kürzer gewesen. Das sollte immer noch für beide Ansätze funktionieren: lc$'!~(T^lc$_%2)oder($_%2x9^lc$')!~T
Dennis

1
@ Tennis für die vorherige Version hätte es Klammern benötigt. !~Tist allerdings genial, danke!
Primo

6

Python 2, 259 253 249 239 Bytes

Probieren Sie es hier aus

Damit kann wohl noch mehr golfen werden.

Bearbeiten: Es wurde ein Fehler behoben, der dazu führte, dass meine nicht 2-4 evenwie erwartet funktionierte . Nehmen Sie dann eine Anpassung für diesen Fix vor. Dieser Fix hat mir vier Bytes gespart!

Bearbeiten: Verwendet jetzt input()und +2 Bytes für die beiden Anführungszeichen, mit denen der Benutzer die Eingabe umgeben muss.

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

Weniger Golf (mit Kommentaren!: D):

Ich hoffe diese Kommentare helfen einigen. Ich bin mir immer noch nicht ganz sicher, ob ich diese letzte komplexe Zeile richtig erklärt habe oder nicht.

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
Nur eine Kleinigkeit, da Sie Python 2 verwenden, können Sie Leerzeichen und Tabulatoren (jeweils 1 Byte) als unterschiedliche Einrückungen verwenden. Relevanter Tipp
FryAmTheEggman

Ich fand auch, dass ich anfangs falsch gezählt hatte. Durch das Kopieren von Registerkarten aus den Editoren werden diese in Leerzeichen umgewandelt.
mbomb007

Sie können mindestens 4 Bytes einsparen, s=raw_input()indem Sie Einrückungen vornehmen und entfernen.

4

Pyth, 43 42 44 42 Bytes

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

Probieren Sie es online aus: Vorführ- oder Testgeschirr

Ich denke, ich kann noch ein oder zwei Bytes hacken.

Erläuterung

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                                      

Funktioniert das mit dem neuesten Testfall?
mbomb007,

@ mbomb007: Das tut es.
Dennis

3

JavaScript (Spidermonkey-Konsole) - 139

Es ist nur einfacher, auf der Kommandozeile zu testen.

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

Kann [,from,to]einfach nur sein [from,to]?
Yytsi

1
@TuukkaX nein, da hiermit der erste Wert des Arrays verworfen wird r.exec, der die gesamte übereinstimmende Zeichenfolge enthält.
Patrick Roberts

3

Faktor - 488 Bytes:

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

Ich glaube nicht, dass ich so viel Golf gespielt habe, aber für eine erste Einreichung nicht schlecht. Kommentierte Version unten.

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

Führen Sie die Testfälle aus:

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"

Je nachdem, wie ich die Regeln gelesen habe, können möglicherweise weitere 4 Bytes gespeichert werden. Wenn gerade / ungerade immer Kleinbuchstaben ist, ${1,,}kann in geändert werden$1


Funktioniert das mit dem neuesten Testfall?
mbomb007,

Einfach getestet und ja, das tut es.
Daniel Wakefield

1

JavaScript ( ES6 ), 149

Führen Sie zum Testen das Snippet in Firefox aus

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

Ich weiß, dass ich zu spät zur Party komme, aber das schien mir ein lustiges Problem zu sein und das Fehlen von Einträgen in Sprachen der C-Familie störte mich.

Hier ist also eine C ++ - Funktion ohne reguläre Ausdrücke oder Zeichenfolgensubstitution, nur ein paar einfache Berechnungen:

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

Ich habe nicht gesagt, dass es lesbar ist, oder? :) Ternäre Operatoren sind die Hölle. Ich habe mein Bestes gegeben, um es zu formatieren, also hoffe ich, dass es zumindest ein bisschen hilft.

Verwendung :

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

Probieren Sie es hier aus

Die Eingabe muss in Anführungszeichen erfolgen

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

Erläuterung:

Der allgemeine Ansatz besteht darin, die vorhandenen Eingaben in gültige Pythons umzuwandeln und diese auszuwerten. Jeder durch Kommas getrennte Wert wird in ein Array konvertiert, das dann alle zusammen angehängt werden und die Länge das Endergebnis ergibt.

Bei der Eingabe 12-15 odd,19führt die Regex-Substitution beispielsweise vor der Auswertung zu folgenden Ergebnissen:

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

Um dies weiter aufzuschlüsseln:

  • 15+1 if 15.0 else 12+1 Dieses Bit stellt sicher, dass das zweite Argument von range () korrekt ist, abhängig davon, ob ein Bereich oder ein einzelner Wert angegeben wurde (wenn \ 3 leer ist, wird \ 3.0 mit false bewertet).
  • if x%2!="oe".find("o")Abhängig von dem Wert, der zwei Zeichen von der letzten Ziffer im Bereich entfernt gefunden wurde ( (?=.(.))im Regex - Lookahead zwei Zeichen, ohne diese zu verbrauchen), gibt es drei mögliche Ergebnisse:

    • x%2!="oe".find("o") bewertet zu x % 2 != 0 (nur ungerade Treffer)
    • x%2!="oe".find("e") bewertet zu x % 2 != 1 (nur gerade passend)
    • x%2!="oe".find("[")ergibt x % 2 != -1(dieses Zeichen kann mehrere Zeichen enthalten, da es nur zwei Zeichen von der letzten Ziffer entfernt ist; es wird jedoch nur dann o oder e sein, wenn ungerade / gerade beabsichtigt ist)
  • Das scheinbar zufällige + [] am Ende soll sicherstellen, dass das letzte Token in der durch Kommas getrennten Liste zwei Zeichen von der letzten Ziffer entfernt ist. Es ermöglicht uns jedoch auch, etwas an das Ende anzuhängen, um das letzte '+' zu verbrauchen. was sonst geschleppt worden wäre.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.