Schließen Sie es heute Abend oder an diesem Wochenende wieder an

20

Dies ist mein erstes Codegolf, also lass es mich bitte wissen, wenn es zu breit ist oder wenn mir Informationen für ein gutes Puzzle fehlen!

Herausforderung

In Ontario und möglicherweise in anderen Regionen der Welt wird die Stromrechnung nach den Nutzungsdauer-Gebühren (Time-Of-Use, TOU) berechnet. Die Kosten pro Kilowattstunde hängen davon ab, wann Sie Strom verbrauchen .

Wenn ich ein Datum und eine Uhrzeit angegeben habe, möchte ich wissen, ob ich mich in einem Zeitraum auf der Spitze (rot), in der Mitte (gelb) oder außerhalb der Spitze (grün) befinde.

Eingang

Angenommen, die Eingabe erfolgt in einem akzeptablen zeitzonenlosen ISO 8601-Datums- / Uhrzeitformat mit einer Mindestgenauigkeit von Stunden: YYYY-MM-DDThh[:mm[:ss]](das T ist ein Literal).

Beispiele

  • 2014-09-01T14
  • 2014-09-01T17: 30
  • 2014-09-01T17: 30: 02

Ausgabe

Die Ausgabe sollte ein String sein On, Midoder Off.

Regeln

  • Kürzester Code gewinnt
  • Ignorieren Sie für diese Herausforderung gesetzliche Feiertage
  • Angenommen, die Informationen in diesem Beitrag gefunden. Die tatsächlichen Regeln für die Preisgestaltung für die Nutzungsdauer könnten sich vom Energieministerium in Ontario in Zukunft ändern.

Information

Sommertage (1. Mai bis 31. Oktober)

Zeitschaltuhr für sommerliche Wochentage

  • Nebensaison: 19.00 - 07.00 Uhr
  • Mittelspitze: 07:00 - 11:00 Uhr und 17:00 - 19:00 Uhr
  • An der Spitze: 11.00 - 17.00 Uhr

Wintertage (1. November bis 30. April)

Uhrzeit für den Winter an Wochentagen

  • Nebensaison: 19.00 - 07.00 Uhr
  • Mittelspitze: 11.00 - 17.00 Uhr
  • An der Spitze: 07:00 - 11:00 Uhr und 17:00 - 19:00 Uhr

Wochenenden

Uhrzeit am Wochenende

  • Nebensaison: Den ganzen Tag
rink.attendant.6
quelle
Sind Sie sicher, dass an den Wintertagen keine Zwischen- / Hauptreisezeiten getauscht wurden?
John Dvorak
3
@JanDvorak, im Winter wird morgens und abends mit Licht und Heizung gearbeitet. im sommer benutzen sie mittags die klimaanlage.
Peter Taylor
4
Dies ist ein Borderline-Duplikat von codegolf.stackexchange.com/q/7008/194 ( Analysieren Sie eine Datums- und Uhrzeitangabe und führen Sie eine einfache Berechnung basierend darauf durch, ob es ein Arbeitstag ist oder nicht). Ich denke, die Saisonabhängigkeit ist gerade unterschiedlich genug, aber andere mögen anderer Meinung sein.
Peter Taylor
@PeterTaylor die Regeln scheinen hier viel einfacher als in der verlinkten Frage. Dies muss zum Beispiel nicht mit Schaltjahren fertig werden.
John Dvorak
3
Sollte das allgemeine Datumsformat so sein, dass YYYY-MM-DDThh[:mm[:ss]]Sekunden nur angewendet werden können, wenn Minuten angewendet werden?
Cruncher

Antworten:

3

Ruby - 147 144 143 141 137 135

x=->s{y,m,d,h=s.scan(/\d+/).map &:to_i
g=Time.new(y,m,d).wday%6<1?0:[0..11,4..9].count{|r|r===h-7}
%W{Off Mid On}[m<5||m>10?(3-g)%3:g]}

Dies stellt eine Funktion dar, die eine Zeichenfolge als Parameter verwendet und eine Zeichenfolge zurückgibt.

Hier ist eine Online-Demo mit einigen Testfällen: http://ideone.com/wyIydw

Cristian Lupascu
quelle
8

Python 2 - 164

from datetime import*
d,t=input().split('T')
y,m,d=map(int,d.split('-'))
t=int(t[:2])
print'OMOfinfd'[(1+((10<t<17)==(4<m<11)))*(date(y,m,d).weekday()<5<6<t<19)::3]

Nachstehend finden Sie bei Bedarf eine Erläuterung der Logik in der letzten Zeile:

Die letzte Zeile druckt 'OMOfinfd'je nach Bewertung ihrer Bedingungen einen Slice aus .

  • Bewerten Sie zuerst die Operation 1+((10<t<17)==(4<m<11)).

    Wenn die XNOR zwischen den Bedingungen 10<t<17und 4<m<11sind False, wird dies bewerten zu 1+False => 1+0 => 1. Andernfalls wird die Operation zu ausgewertet 1+True => 1+1 => 2.

  • Multiplizieren Sie abschließend das Ergebnis der obigen Operation mit der Angabe, ob der Tag ein Wochentag ist und ob die Zeit zwischen 6 und 19 Uhr liegt.

    Wenn dies Falseder Fall ist , ist entweder der Tag ein Wochenende oder die Zeit zwischen 19.00 und 06.00 Uhr und das Ergebnis ist (1|2)*0 => 0. Andernfalls ist das Ergebnis (1|2)*1 => 1|2.

Ein Ergebnis von 0wird gedruckt Off, 1wird gedruckt Midund 2wird gedruckt On.

BeetDemGuise
quelle
Ist die Golfversion nicht länger, weil Sie Semikolons verwenden? Oder werden Zeilenumbrüche gezählt?
Beta Decay
Zeilenumbrüche werden normalerweise gezählt. In Notepad ++ (wo ich normalerweise meine Anzahl erhalte) ist die ungolfed Version 4 Bytes länger bei 168.
BeetDemGuise
3
@BeetDemGuise Bearbeiten → EOL-Konvertierung → UNIX / OSX-Format.
Schism
5

C # - 240 220 Zeichen

string x(string s){var d=DateTime.Parse((s+":00:00").Substring(0,19));int h=d.Hour,i=(int)d.DayOfWeek,x=d.Month;string o="off",m="mid",f="on";return i==6|i==0?o:x>=5&x<11?h>18|h<7?o:h>10&h<17?f:m:h>18|h<7?o:h>10&h<17?m:f;}

Nichts Besonderes. Einfache Codierung.

Danke an w0lf :)

Stephan Schinkel
quelle
1
Ich denke, Sie können s.Length==13?s+":00:00":s.Length==16?s+":00":sbis(s+":00:00").Substring(0,19)
Cristian Lupascu
5

Rubin - 135

Missbrauch des Zeitmoduls. Eingabe über Befehlszeilenargument.

d=Time.new(*$*[0].scan(/\d+/)[0..3])
o,m,f=%w{On Mid Off}
o,m=m,o if (d.mon-5)%10<6
p d.wday%6<1||(12>h=(d.hour+5)%24)?f:15<h&&h<22?m:o

Edit: Danke w0lf für die Zeit, die geholfen hat, einen Bug zu verkürzen und zu lösen.

Vektorisiert
quelle
Ihr Programm ist falsch. Für den Eingang gibt 2014-09-01T17:30es richtig aus "Mid", aber dafür 2014-09-01T17gibt es aus "Off".
Cristian Lupascu
3

Groovy - 621 534 524 491 Zeichen

Weiteres Golfen, aber ganz einfach mit Joda-Time

@Grab(group='joda-time',module='joda-time',version='2.3')
f={p,a->org.joda.time.format.DateTimeFormat.forPattern(p).parseDateTime a}
g={p,a->def x=null;try{x=f p,a}catch(Exception e){}}
a=args[0]
d=["",":mm",":mm:ss"].collect{g "yyyy-MM-dd'T'HH$it",a}.find{it}
r="Off"
m="Mid"
j={d,a,b->d.hourOfDay>a&&d.hourOfDay<b}
k={j(it,6,11)||(j(it,16,19))}
if(d.dayOfWeek<6){x=d.monthOfYear;if(x>4&&x<12){if(j(d,10,17))r="On";if(k(d))r=m}else if(x<5||x>10){if(j(d,10,17))r=m;if(k(d))r="On"}}
println r

Probeläufe:

bash-3.2$ ./run.peak.sh 
groovy Peak.groovy 2014-08-26T19
Off
groovy Peak.groovy 2014-08-26T07:00
Mid
groovy Peak.groovy 2014-08-26T18:00:00
Mid
groovy Peak.groovy 2014-08-26T12:30:30
On
groovy Peak.groovy 2014-11-01T00
Off
groovy Peak.groovy 2014-02-05T11:11:11
Mid
groovy Peak.groovy 2014-01-05T08:08
Off
groovy Peak.groovy 2014-12-18T18:59:59
On
groovy Peak.groovy 2014-08-31T14
Off

Ungolfed:

@Grab(group='joda-time',module='joda-time',version='2.3')

f = { p,a -> org.joda.time.format.DateTimeFormat.forPattern(p).parseDateTime a}
g = { p,a -> def x=null; try{x=f p,a} catch(Exception e) {} }
a=args[0]

d = ["",":mm",":mm:ss"].collect{g "yyyy-MM-dd'T'HH$it",a}.find{it}
r = "Off"
m = "Mid"

j = {d,a,b -> d.hourOfDay > a && d.hourOfDay < b}
k = { j(it,6,11) || (j(it,16,19)) }

if (d.dayOfWeek<6) {
    x = d.monthOfYear;
    if ( x>4 && x<12 ) {
        if (j(d,10,17)) r="On";
        if (k(d)) r=m
    } else if (x<5||x>10) {
        if (j(d,10,17)) r=m;
        if (k(d)) r="On"
    }
}
println r
Michael Easter
quelle
2
Seit Java 8 gibt es auch java.time.*, das Joda Time sehr ähnlich ist, aber Teil der JRE ist. Vielleicht könnte dies den Code etwas verkürzen.
ntoskrnl
re: Java 8. ausgezeichneter Punkt
Michael Easter
In Ihrem vorletzten Beispiel '2014-01-05T08:08'ist der 5. Januar 2014 ein Sonntag. So sollte es sein'Off'
BeetDemGuise
Betreff: 5. Januar 2014. Ganz richtig. Der aktuelle Code ist korrekt, aber der Ausgabelauf ist falsch. Wird reparieren.
Michael Ostern
Versucht java.time.*. Scheiterte kläglich. Der Parser ist zu streng. Verwenden Sie DateParseraus Nashorn (ebenfalls Teil des JRE8), das mild und mit ein wenig missbräuchlichem Hacking sogar mild genug ist, um Minuten und Sekunden zu überspringen.
Mark Jeronimus
2

R, 243 204 Zeichen

b=strptime(scan(,""),"%Y-%m-%dT%H");i=function(x)as.integer(format(b,x));h=i("%H");d=i("%m%d");w=d>1100|d<430;f=ifelse;cat(c("Off","Mid","On")[f(i("%u")%in%5:6|h<7|h>19,1,f(h>11&h<17,f(w,2,3),f(w,3,2)))])

Eingerückt und kommentiert:

b=strptime(scan(,""),"%Y-%m-%dT%H") #Takes stdin and converts into POSIXct
i=function(x)as.integer(format(b,x)) #Format the POSIXct and convert it to integer
h=i("%H")      #Format to hours
d=i("%m%d")    #Format to Month/Day
w=d>1100|d<430 #True if winter time, false if summer
f=ifelse
cat(c("Off","Mid","On")[f(i("%u")%in%5:6|h<7|h>19, #If weekend or night
                          1,                       #Case 1
                          f(h>11&h<17,            #Else if mid-day
                             f(w,3,2),             #Case 2 in winter, case 3 in summer
                             f(w,2,3)))])          #else vice versa

Beispiele:

> b=strptime(scan(,""),"%Y-%m-%dT%H");i=function(x)as.integer(format(b,x));h=i("%H");d=i("%m%d");w=d>1100|d<430;f=ifelse;cat(c("Off","Mid","On")[f(i("%u")%in%5:6|h<7|h>19,1,f(h>11&h<17,f(w,3,2),f(w,2,3)))])
1: 2014-08-26T15
2: 
Read 1 item
On
> b=strptime(scan(,""),"%Y-%m-%dT%H");i=function(x)as.integer(format(b,x));h=i("%H");d=i("%m%d");w=d>1100|d<430;f=ifelse;cat(c("Off","Mid","On")[f(i("%u")%in%5:6|h<7|h>19,1,f(h>11&h<17,f(w,3,2),f(w,2,3)))])
1: 2014-12-10T15
2: 
Read 1 item
Mid
> b=strptime(scan(,""),"%Y-%m-%dT%H");i=function(x)as.integer(format(b,x));h=i("%H");d=i("%m%d");w=d>1100|d<430;f=ifelse;cat(c("Off","Mid","On")[f(i("%u")%in%5:6|h<7|h>19,1,f(h>11&h<17,f(w,3,2),f(w,2,3)))])
1: 2014-08-26T23
2: 
Read 1 item
Off
Plannapus
quelle
1

Bash, 286

Dies ist eine einfache Bash-Antwort mit dem Datumsprogramm

d(){ date -d $1 +%$2; };D=$(echo $1|sed 's/\(T..\)$/\1:00/');H=$(d $D H);M=$(d $D m);if [ $(d $D u) -gt 5 ]||[ $H -lt 7 ]||[ $H -gt 18 ];then echo Off;exit;fi;if [ $M -gt 4 ]&&[ $M -lt 11 ];then I=On;O=Mid;else I=Mid;O=On;fi;if [ $H -gt 10 ]&&[ $H -lt 17 ];then echo $I;else echo $O;fi
Optokopper
quelle
1

Hier geht noch einer!

JavaScript, 175 171

function f(x){d=new Date(x.slice(0,10));t=x.slice(11,13),m=(x.slice(5,7)+1)%12;return(t<8||t>18||!(d.getUTCDay()%6)?'off':((t<11||t>17)?(m<5?'on':'mid'):(m<5?'mid':'on'))}

Nicht abgeschlossen:

function f(x) {
  d = new Date(x.slice(0, 10));
  t = x.slice(11, 13), m = (x.slice(5, 7) + 1) % 12;
  return (t < 8 || t > 18 || !(d.getUTCDay() % 6) ? 'off' : ((t < 11 || t > 17) ? (m < 5 ? 'on' : 'mid') : (m < 5 ? 'mid' : 'on'))
}

Funktioniert nur mit Interpreten, bei denen eine ISO8601-Datumszeichenfolge an den DateKonstruktor übergeben werden kann.

CoffeeScript, 192 189

Überraschenderweise ist es in CoffeeScript länger, da es in dieser Sprache keinen ternären Operator gibt (worauf ich mich in meinem JavaScript stark verlassen habe).

f=(x)->d=new Date(x.slice(0,10));t=x.slice(11,13);m=(x.slice(5,7)+1)%12;return'off'if(t<8||t>18||!(d.getUTCDay()%6));if(t<11||t>17)then(if m<5then'on'else'mid')else(if m<5then'mid'else'on')
rink.attendant.6
quelle
0

ES6 - 146

Dies ist in Funktionsform, verwendet ein paar böse Hacks.

let y,m,d,h,c=s=>[y,m,d,h]=s.split(/[T:-]/g).map(i=>+i),new Date(y,m,d).getDay()in{0:1,6:1}||h<20||8>h?'Off':['Mid','On'][(10>h&&h>16)^(m>5||m<8)]

Erklärt:

// These variables are declared outside of the function scope to save
// characters.
let y, // year
    m, // month
    d, // day
    h, // hour
    c = s => // c for check, called as c(isoString)
      [y, m, d, h] = // Assign to fields
        s.split(/[T:-]/g) // Split at delimiters
         .map(i => +i), // Convert all to numbers
                        // Comma used to keep it as a single statement.
      new Date(y, m, d).getDay() // Create Date to get day of week
        in {0:1, 6:1} // Check if it is good (0 = Sunday, 6 = Saturday). It
                      // is shorter to use an object literal than to
                      // do individual checks.
      ||
      h < 20 || 8 > h ? // h is between 7 and 19 (7pm)
       'Off' : // Return 'Off'
       ['Mid','On'][ // Two other outputs
        (10 > h && h > 16) ^ // Check if it is 11-16 (5pm)
        (m > 5 || m < 8)] // Invert that if the month is in summer/fall. Note
                          // that this returns a number, either 1 or 0. This
                          // is an ugly hack using the bitwise xor operator.
Isiah Meadows
quelle
0

Python 3 - 352 Zeichen

import datetime as dt
t=input()
i=int
p=print
a='on'
b='mid'
c='off'
m=i(t[5:7])
h=i(t[11:13])
d=dt.date(i(t[0:4]),m,i(t[8:10])).weekday()
if 5==d or 6==d:p(c)
elif h>=19 and h<7:p(c)
elif m<=10 and m>=4:
 if h>=7 and h<11:p(b)
 if h>=11 and h<17:p(a)
 if h>=17 and h<19:p(b)
else:
 if h>=7 and h<11:p(a)
 if h>=11 and h<17:p(b)
 if h>=17 and h<19:p(a)
Beta-Zerfall
quelle
1
Sie sollten ändern s=['high','mid','off']zu s=['on','mid','off']- nicht nur dies tun speichern 2 Zeichen, aber die Spezifikation sagt zur Ausgabe von „on“.
Sellyme
0

Java - 426 309/301? (Zeige Kommentare)

String z(String a){
    DateParser b=new DateParser(a);
    boolean c=b.parseEcmaDate();
    Integer[]d=b.getDateFields();
    GregorianCalendar e=new GregorianCalendar(d[0],d[1]-(c?0:1),d[2]);
    e.setTimeZone(new SimpleTimeZone(0,""));
    return(124>>e.get(7)&1)>0&d[3]>6&d[3]<19?
           d[3]>10&d[3]<17^(1008>>e.get(2)&1)>0?"Mid":"On":"Off";
}

Beispielausgabe:

2014-03-02T00   Off
2014-03-02T06   Off
2014-03-02T07   Off
2014-03-02T10   Off
2014-03-02T11   Off
2014-03-02T16   Off
2014-03-02T17   Off
2014-03-02T18   Off
2014-03-02T19   Off
2014-03-02T23   Off
2014-04-02T00   Off
2014-04-02T06   Off
2014-04-02T07   On
2014-04-02T10   On
2014-04-02T11   Mid
2014-04-02T16   Mid
2014-04-02T17   On
2014-04-02T18   On
2014-04-02T19   Off
2014-04-02T23   Off
2014-05-02T00   Off
2014-05-02T06   Off
2014-05-02T07   Mid
2014-05-02T10   Mid
2014-05-02T11   On
2014-05-02T16   On
2014-05-02T17   Mid
2014-05-02T18   Mid
2014-05-02T19   Off
2014-05-02T23   Off

Ich habe den gleichen EXOR-Trick wie die Python-Vorlage verwendet. Ich habe auch eine +als OR-Funktion verwendet, wenn es ist weekend OR night.

Mein anderer großer Trick: Bitmasken.

Um beispielsweise festzustellen, ob eine Zahl zwischen 2 und 6 liegt (Montag bis Freitag), erstellen Sie zunächst ein Bitmuster mit den interessanten Werten 1:

  6   2 
0b1111100 = 124

Verwenden Sie dann die Bitverschiebung, um das interessante Bit in das LSB zu übertragen und zu extrahieren:

(124 >> day_of_week) & 1

Ebenso habe ich monatelang und stundenlang Bitmuster erstellt:

  9    4
0b1111110000 = 1008

      76          76
0b111110000000000001111111 = 16253055
0b000000011111100000000000 = 129024

Leider stellt sich heraus, dass es x>y&x<zin den meisten Fällen einfach kürzer ist, so dass ich es an einigen Stellen nicht verwendet habe.

Und zum Schluss noch ein bisschen Hackery (stark implementierungsabhängig) mit jdk.nashorn.internal.parser.DateParser: Wenn parseEcmaDate()ein Datum nicht vollständig analysiert wird (z. B. wenn es die Stunde liest und das Ende der Zeichenfolge erreicht), wird false zurückgegeben.

  • Wenn es richtig beendet ist, wird das Datum in einem Integer[](Auto-Unboxing-FTP) gespeichert , wobei der Monat auf Basis 0 festgelegt ist (wie bei anderen Java-Klassen).
  • Wenn es false zurückgibt, wurde es zur Hälfte abgebrochen und hat diese Korrektur nicht durchgeführt. Es wurde jedoch immer noch alles, was es analysierte, in das Array eingefügt, das sofort verfügbar ist. Daher die -(c?0:1).
Mark Jeronimus
quelle
Ich denke, es .parse()könnte auch funktionieren, nur 8 Zeichen zu verwenden, aber ich habe es nicht gründlich mit verschiedenen Eingaben getestet. parseIntern ruft an parseEcmaDateund wenn es fehlschlägt, ruft an parseLegacyDate. Letzteres kann das Array vermasseln, aber dies ist in einigen Fällen, die ich getestet habe, nicht geschehen.
Mark Jeronimus
-1

Nichts hindert mich daran, meine eigenen zu betreten, und es gibt hier sowieso noch andere kürzere, also ...

PHP 5.4+, 194

<?function f($x){$t=substr($x,11,2);$m=(substr($x,5,2)+1)%12;if($t<8||$t>18||(new DateTime(substr($x,0,10)))->format('N')>5)return'off';return($t<11||$t>17)?($m<5?'on':'mid'):($m<5?'mid':'on');}

Nicht abgeschlossen und kommentiert:

<?
function f($x) {
  $t = substr($x,11,2); // hour
  $m = (substr($x,5,2) + 1) % 12; // month shifted up by 1

  if ($t < 8 || $t > 18 || (new DateTime(substr($x,0,10)))->format('N') > 5)
    return 'off'; // evenings and weekends

  return ($t < 11 || $t > 17)
    ? ($m < 5 ? 'on' : 'mid') // morning and mid-afternoon
    : ($m < 5 ? 'mid' : 'on'); // afternoon
}

Beachten Sie auch, dass die date.timezoneDirektive in der php.ini gesetzt sein muss, sonst wird eine Exception ausgelöst.

rink.attendant.6
quelle