Pasang kembali di malam ini atau akhir pekan ini

20

Ini adalah kode golf pertama saya, jadi tolong beri tahu saya jika terlalu luas atau jika saya kehilangan informasi untuk puzzle yang bagus!

Tantangan

Di Ontario dan mungkin daerah lain di dunia, listrik ditagih menggunakan Time-Of-Use (TOU) , yang memvariasikan biaya per kilowatt-jam sesuai dengan saat Anda menggunakan daya.

Diberi tanggal dan waktu, saya ingin tahu apakah saya berada di periode waktu on-peak (merah), mid-peak (kuning), atau off-peak (hijau).

Memasukkan

Asumsikan bahwa input disediakan dalam format tanggal-waktu ISO 8601 kurang-zona waktu yang dapat diterima dengan ketepatan jam minimum:YYYY-MM-DDThh[:mm[:ss]] (T adalah literal).

Contohnya

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

Keluaran

Output harus string On, MidatauOff .

Aturan

  • Kode terpendek menang
  • Untuk tujuan tantangan ini, abaikan hari libur resmi
  • Asumsikan informasi yang ditemukan di pos ini. Aturan aktual penetapan harga waktu penggunaan mungkin berubah di masa depan oleh Kementerian Energi Ontario.

Informasi

Musim panas hari kerja (1 Mei hingga 31 Oktober)

Jam penggunaan waktu untuk musim panas hari kerja

  • Off-peak: 19h00 - 07h00
  • Mid-peak: 07h00 - 11h00 dan 17h00 - 19h00
  • On-peak: 11h00 - 17h00

Musim dingin di musim dingin (1 November hingga 30 April)

Jam penggunaan waktu untuk hari kerja musim dingin

  • Off-peak: 19h00 - 07h00
  • Mid-peak: 11h00 - 17h00
  • On-peak: 07h00 - 11h00 dan 17h00 - 19h00

Akhir pekan

Waktu penggunaan jam pada akhir pekan

  • Off-peak: Sepanjang hari
rink.attendant.6
sumber
Apakah Anda yakin hari kerja musim dingin tidak memiliki pertukaran pertengahan-puncak / puncak?
John Dvorak
3
@JanDvorak, di musim dingin orang menggunakan lampu dan pemanas di pagi dan sore hari; di musim panas mereka menggunakan AC di tengah hari.
Peter Taylor
4
Ini adalah duplikat borderline dari codegolf.stackexchange.com/q/7008/194 (parsing suatu kurun waktu dan lakukan perhitungan sederhana berdasarkan apakah itu hari kerja atau tidak). Saya pikir ketergantungan musim hanya cukup berbeda, tetapi yang lain mungkin tidak setuju.
Peter Taylor
@PeterTaylor aturannya tampak lebih sederhana di sini daripada di pertanyaan terkait. Ini tidak harus menangani tahun kabisat, misalnya.
John Dvorak
3
Haruskah format tanggal umum YYYY-MM-DDThh[:mm[:ss]]sejak detik hanya dapat diterapkan jika menit diterapkan?
Cruncher

Jawaban:

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

Ini mewakili fungsi yang mengambil string sebagai parameter dan mengembalikan string.

Ini demo online dengan beberapa test case: http://ideone.com/wyIydw

Cristian Lupascu
sumber
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]

Jika diperlukan, di bawah ini adalah penjelasan dari logika di baris terakhir:

Baris terakhir mencetak sepotong 'OMOfinfd'tergantung pada evaluasi kondisionalnya.

  • Pertama, evaluasi operasi 1+((10<t<17)==(4<m<11)).

    Jika XNOR berada di antara kondisi 10<t<17dan 4<m<11adalah False, ini akan dievaluasi menjadi 1+False => 1+0 => 1. Jika tidak, operasi akan dievaluasi menjadi 1+True => 1+1 => 2.

  • Akhirnya, gandakan hasil operasi di atas dengan apakah hari itu adalah hari kerja dan apakah waktunya antara pukul 6 pagi sampai 7 sore.

    Jika demikian False, hari itu adalah akhir pekan atau waktunya adalah antara jam 7 malam - 6 pagi, dan hasilnya akan seperti itu (1|2)*0 => 0. Kalau tidak hasilnya akan (1|2)*1 => 1|2.

Hasil dari 0akan dicetak Off, 1akan dicetak Mid, dan 2akan dicetak On.

BeetDemGuise
sumber
Bukankah versi golf sebenarnya lebih lama karena Anda menggunakan titik koma? Atau baris baru dihitung?
Beta Decay
Baris baru biasanya dihitung. Dalam Notepad ++ (di mana saya biasanya mendapatkan hitungan saya) versi ungolfed adalah 4bytes lagi di 168.
BeetDemGuise
3
@BeetDemGuise Edit → Konversi EOL → Format UNIX / OSX.
Skisma
5

C # - 240 220 karakter

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

Tidak ada yang spesial. Pengodean lurus ke depan.

Terima kasih kepada w0lf :)

Stephan Schinkel
sumber
1
Saya pikir Anda dapat mempersingkat s.Length==13?s+":00:00":s.Length==16?s+":00":ske(s+":00:00").Substring(0,19)
Cristian Lupascu
5

Ruby - 135

Menyalahgunakan modul Waktu. Masukan dengan argumen baris perintah.

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

Sunting: Terima kasih w0lf untuk Waktu yang membantu mempersingkat dan menyelesaikan bug.

Vektor
sumber
Program Anda salah. Untuk input 2014-09-01T17:30dengan benar output "Mid", tetapi untuk 2014-09-01T17itu output "Off".
Cristian Lupascu
3

Groovy - 621 534 524 491 karakter

Beberapa bermain golf lebih lanjut untuk dilakukan, tetapi cukup sederhana ketika memanfaatkan 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

sampel berjalan:

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

Tidak Terkumpul:

@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
sumber
2
Sejak Java 8, ada juga java.time.*, yang sangat mirip dengan Joda Time tetapi merupakan bagian dari JRE. Mungkin ini bisa mempersingkat kode sedikit.
ntoskrnl
re: Java 8. titik luar biasa
Michael Easter
Dalam contoh 3-ke-terakhir Anda '2014-01-05T08:08', 5 Januari 2014 adalah hari Minggu. Dengan demikian, seharusnya'Off'
BeetDemGuise
re: 5 Jan 2014. Benar sekali. Kode saat ini benar, tetapi menjalankan output salah. Akan memperbaiki.
Michael Easter
Mencoba java.time.*. gagal total. Pengurai terlalu ketat. Gunakan DateParserdari nashorn (juga bagian dari JRE8) yang lunak, dan dengan sedikit peretasan kasar, bahkan cukup ringan untuk melewati menit & detik.
Mark Jeronimus
2

R, 243 204 karakter

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

Diindentasi dan berkomentar:

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

Contoh:

> 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
sumber
1

Bash, 286

ini adalah jawaban bash sederhana menggunakan program tanggal

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
sumber
1

Ini dia lagi!

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'))}

Tidak dijinakkan:

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'))
}

Hanya bekerja pada penterjemah tempat string tanggal ISO8601 dapat diteruskan ke Datekonstruktor.

CoffeeScript, 192 189

Anehnya, itu lebih lama di CoffeeScript karena tidak ada operator ternary dalam bahasa itu (yang seperti yang Anda lihat dari JavaScript saya, saya sangat bergantung pada).

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
sumber
0

ES6 - 146

Ini dalam bentuk fungsi, menggunakan beberapa hack jahat.

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

Dijelaskan:

// 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
sumber
0

Python 3 - 352 karakter

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)
Peluruhan Beta
sumber
1
Anda harus mengubah s=['high','mid','off']ke s=['on','mid','off']- tidak hanya ini menyimpan 2 karakter, tetapi spesifikasi mengatakan untuk menampilkan "pada".
Sellyme
0

Java - 426 309/301? (lihat komentar)

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

Contoh output:

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

Saya menggunakan trik EXOR yang sama dengan pengiriman Python. Saya juga menggunakan +fungsi OR, untuk saat itu weekend OR night.

Trik besar saya yang lain: topeng bit.

Misalnya, untuk melihat apakah angka berada di antara 2 dan 6 (Senin hingga Jumat), pertama buat pola bit di mana nilai yang menarik adalah 1:

  6   2 
0b1111100 = 124

Kemudian, gunakan bit shift untuk mendapatkan bit yang menarik ke LSB dan ekstrak:

(124 >> day_of_week) & 1

Demikian pula, saya membuat pola bit selama berbulan-bulan dan berjam-jam:

  9    4
0b1111110000 = 1008

      76          76
0b111110000000000001111111 = 16253055
0b000000011111100000000000 = 129024

Sayangnya, ternyata x>y&x<zlebih pendek dalam banyak kasus, jadi saya tidak menggunakannya di beberapa tempat.

Dan akhirnya, sedikit peretasan (sangat tergantung implementasi) dengan jdk.nashorn.internal.parser.DateParser: KapanparseEcmaDate() tidak sepenuhnya menguraikan tanggal (seperti ketika membaca jam dan mencapai akhir string), ia mengembalikan false.

  • Ketika selesai dengan benar, tanggal disimpan dalam Integer[] (ftw auto-unboxing), dengan bulan ditetapkan menjadi basis-0 (seperti kelas Java lainnya).
  • Ketika kembali salah, itu dibatalkan setengah jalan dan tidak melakukan perbaikan ini. Namun itu tetap memasukkan apa pun yang diuraikan ke dalam array, yang sudah tersedia. Karena itu -(c?0:1).
Mark Jeronimus
sumber
Saya pikir menggunakan .parse()mungkin juga berfungsi (mengurangi 8 karakter), tapi saya belum mengujinya dengan input yang berbeda. parsepanggilan internal parseEcmaDatedan jika gagal, panggilan parseLegacyDate. Yang terakhir mungkin mengacaukan array, tetapi ini tidak terjadi dengan beberapa kasus yang saya uji.
Mark Jeronimus
-1

Tidak ada yang menghentikan saya untuk memasukkan milik saya, dan ada yang lebih pendek di sini, jadi ...

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

Tidak ditagih dan dikomentari:

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

Perhatikan juga bahwa date.timezonearahan dalam php.ini harus disetel, jika tidak, Pengecualian akan dibuang.

rink.attendant.6
sumber