Zarządzanie kolejkami w Czarny piątek

10

Wprowadzenie

Jesteś kierownikiem działu elektroniki w dużym sklepie detalicznym, a największy dzień sprzedaży w tym roku to piątek . Aby pomóc w zarządzaniu tłumami, Twój sklep wdraża system biletów na największe okazje, w których klienci muszą przedstawić bilet przed zakupem produktu. Twoim zadaniem jest napisanie programu do sprawdzania poprawności biletów.

Ponieważ jedynym dostępnym komputerem w sklepie (z powodu cięć budżetowych) jest dinozaur ze złamaną klawiaturą (a wszystko, co masz, to klawiatury USB, które nie są kompatybilne), będziesz musiał wprowadzić swój program za pomocą myszy. Dlatego twój program powinien być jak najkrótszy.

Produkty

Twój sklep prowadzi sprzedaż pięciu różnych produktów wymienionych poniżej. Każdy produkt ma małą literę i inne zasady określające, ile można kupić i o której porze dnia.

  • television: Dostępne są 5telewizory z płaskim ekranem, które można kupić od 00:00:00(do północy) do 00:59:59.
  • smartphone: W 10magazynie są smartfony, ale każdy klient w kolejce od 00:00:00(do północy) 00:59:59otrzymuje kupon na jeden, gdy skończy się.
  • tablet: Istnieją 10tablety, które można kupić w dowolnym momencie.
  • laptop: Istnieje nieograniczona liczba laptopów, które można kupić od 00:00:00(do północy) do 07:59:59.
  • lightbulb: Istnieje nieograniczona liczba żarówek, które można kupić w dowolnym momencie.

Wejście

Ciąg wieloliniowy z każdą linią w następującym formacie. Linie są sortowane według znacznika czasu.

<time stamp> <product name> <ticket number>
  • Numer biletu składa się z 8 cyfr. Ostatnia cyfra jest cyfrą kontrolną równą sumie pierwszych siedmiu cyfr modulo 10. Aby był ważny, numer biletu musi mieć poprawną cyfrę kontrolną i musi być ściśle większy niż wszystkie poprzednie numery biletów.
  • Nazwa produktu jest jednym z ciągów wymienionych powyżej.
  • Znacznik czasu jest pora dnia, w formacie HH:MM:SS, gdzie HHjest dwucyfrowa godzina od 00-23, a MMi SSsą minut dwucyfrowa a drugi odpowiednio.

Wynik

Dane wyjściowe to jeden z następujących ciągów, z jednym wierszem na bilet. Warunki muszą być stosowane w kolejności .

  1. Expired offer (Dotyczy telewizorów, smartfonów i laptopów.) Znacznik czasu na bilecie jest po godzinie granicznej na zakup produktu.
  2. Invalid ticket Numer biletu jest mniejszy lub równy numerowi poprzedniego biletu lub cyfra kontrolna jest nieprawidłowa.
  3. Give voucher (Dotyczy smartfonów.) Produkt nie jest dostępny w magazynie, ale wszyscy klienci w kolejce przed wygaśnięciem oferty dostają kontrolę deszczu.
  4. Out of stock(Dotyczy telewizorów i tabletów.) Cały produkt został sprzedany. Przepraszamy, ilość była ograniczona.
  5. AcceptedWszystkie warunki są spełnione, więc daj im produkt. Pamiętaj, że tylko zaakceptowane bilety zmniejszają liczbę produktów w magazynie.

Przykład

Input                           Output
----------------------------    --------------
00:00:00 television 00010001    Accepted
00:00:25 smartphone 00011697    Accepted
00:01:25 laptop 00030238        Accepted
00:02:11 smartphone 00037291    Accepted
00:02:37 lightbulb 00073469     Invalid ticket
00:03:54 smartphone 00096319    Accepted
00:05:26 tablet 00152514        Accepted
00:06:21 tablet 00169893        Accepted
00:07:10 television 00190268    Accepted
00:07:47 smartphone 00194486    Accepted
00:07:55 tablet 00220071        Accepted
00:08:20 lightbulb 00321332     Accepted
00:10:01 smartphone 00409867    Accepted
00:11:10 tablet 00394210        Invalid ticket
00:11:46 television 00581060    Accepted
00:12:44 lightbulb 00606327     Accepted
00:13:16 tablet 00709253        Accepted
00:13:53 television 00801874    Accepted
00:14:47 laptop 00832058        Accepted
00:15:34 smartphone 00963682    Accepted
00:16:24 smartphone 01050275    Accepted
00:17:45 tablet 01117167        Accepted
00:18:05 laptop 01107548        Invalid ticket
00:19:00 lightbulb 01107605     Invalid ticket
00:19:47 lightbulb 01492983     Accepted
00:19:50 smartphone 01561609    Accepted
00:21:09 television 01567098    Accepted
00:21:42 laptop 01597046        Accepted
00:22:17 smartphone 01666313    Accepted
00:24:12 tablet 01924859        Accepted
00:24:12 smartphone 02151571    Accepted
00:25:38 smartphone 02428286    Give voucher
00:31:58 television 02435284    Out of stock
00:35:25 television 02435295    Out of stock
00:52:43 laptop 02657911        Invalid ticket
00:53:55 smartphone 02695990    Give voucher
01:08:19 tablet 02767103        Accepted
01:34:03 television 02834850    Expired offer
01:56:46 laptop 02896263        Accepted
02:02:41 smartphone 03028788    Expired offer
02:30:59 television 03142550    Expired offer
02:51:23 tablet 03428805        Accepted
03:14:57 smartphone 03602315    Expired offer
03:27:12 television 03739585    Expired offer
03:56:52 smartphone 03997615    Expired offer
04:07:52 tablet 04149301        Accepted
04:12:05 lightbulb 04300460     Invalid ticket
04:24:21 laptop 04389172        Accepted
04:40:23 lightbulb 04814175     Accepted
04:40:55 tablet 04817853        Accepted
04:42:18 smartphone 04927332    Expired offer
05:06:43 tablet 05079393        Out of stock
05:16:48 tablet 05513150        Out of stock
05:33:02 television 05760312    Expired offer
05:43:32 tablet 06037905        Out of stock
06:12:48 smartphone 06440172    Expired offer
06:35:25 laptop 06507277        Accepted
06:42:29 lightbulb 06586255     Invalid ticket
06:55:31 lightbulb 06905583     Accepted
06:55:33 lightbulb 06905583     Invalid ticket
07:40:05 smartphone 07428006    Expired offer
07:49:12 television 07588086    Expired offer
08:14:56 laptop 08111865        Expired offer

Starałem się, aby przykład obejmował każdy możliwy scenariusz wyjściowy, ale proszę zostawić komentarz, jeśli coś jest niejasne.

To jest , możesz napisać program lub funkcję, a standardowe pętle są niedozwolone.

intrepidcoder
źródło

Odpowiedzi:

5

JavaScript (ES6), 396 433 419 bajtów

h=0;f=1/0;i={television:{c:5,s:0,e:1},smartphone:{c:10,s:0,e:1,v:1},tablet:{c:10,s:0,e:24},laptop:{c:f,s:0,e:8},lightbulb:{c:f,s:0,e:24}};while(1){t=prompt().split(' ');a=t[0];r=a[0]+a[1]-0;o=i[t[1]];m=0;z='Accepted';u=t[2]-0;u<=h||(u-u%10+'').split('').reduce((p,c)=>-(-p-c))%10!=u%10?m='Invalid ticket':0;r<o.s||r>=o.e?m='Expired offer':0;if(!m)o.c?o.c--:(o.v?z='Give voucher':m='Out of stock');!m?h=u:0;alert(m?m:z)}

Edycja: Zmniejszony rozmiar za pomocą funkcji dużej strzałki es6

Bardziej czytelny:

h=0
f=1/0
i={television:{c:5,s:0,e:1},smartphone:{c:10,s:0,e:1,v:1},tablet:{c:10,s:0,e:24},laptop:{c:f,s:0,e:8},lightbulb:{c:f,s:0,e:24}}
while(1){t=prompt().split(' ')
a=t[0]
r=a[0]+a[1]-0
o=i[t[1]]
m=0
z='Accepted'
u=t[2]
if(u<=h||(u-u%10+'').split('').reduce(function(p,c){return-(-p-c)})%10!=u%10)m='Invalid ticket'
if(r<o.s||r>=o.e)m='Expired offer'
if(!m){if(o.c)o.c--
else o.v?z='Give voucher':m='Out of stock'}if(!m)h=u
alert(m?m:z)}

Co ciekawe, dłuższy kod jest szybszy: http://jsperf.com/compare-read

GUI z tą samą logiką:

var app = angular.module('app', []);

app.controller('MainCtrl', function MainCtrl ($scope) {
  $scope.items = {
    television: {c: 5, s:0, e: 1},
    smartphone: {c: 10, s:0, e: 1},
    tablet: {c:10, s:0, e: 24},
    laptop: {c:Infinity, s: 0, e: 8},
    lightbulb: {c: Infinity, s: 0, e: 24},
  };
  
  var h = -1;//highest
  
  $scope.hours_offset = 0;
  
  $scope.ticket = {};
  for (var i = 0; i < 8; i++) $scope.ticket[i] = 0;
  
  $scope.selected_item = -1;
  
  $scope.nums = new Array(10);
  
  $scope.history = [];
  
  $scope.buy = function() {
    
  }
  $scope.selectItem = function($i) {
    $scope.selected_item = $i;
  }
  
  $scope.purchase = function() {
    if ($scope.selected_item === -1)
      return;

    var ticnum = '';
    var msg = 'Accepted';
    
    for(var key in $scope.ticket)
      ticnum+=$scope.ticket[key];
    
    var d = new Date();
    
    //Variable declarations to setup for code like the code I designed for console
    r = d.getHours()-$scope.hours_offset;//hour
    o = $scope.items[$scope.selected_item];//item
    m = 0//msg
    z = 'Accepted'//default_msg
    u=ticnum
    
    //This is copied from my console code
    if(ticnum<=h||(ticnum-ticnum%10+'').split('').reduce(function(p,c){return-(-p-c)})%10!=ticnum%10)m='Invalid ticket'
	if(r<o.s||r>=o.e)m='Expired offer'
	if(!m){if(o.c)o.c--
	else o.v?z='Give voucher':m='Out of stock'}if(!m)h=ticnum
	
    msg = m?m:z;
    
    $scope.history.unshift({
      time: time(d),
      item: $scope.selected_item,
      ticket_num: ticnum,
      message: msg
    });
    
  }
});

function time(date) {
  return padToTwo(date.getHours()) + ':' + padToTwo(date.getMinutes()) + ':' + padToTwo(date.getSeconds());
}
    
function padToTwo(number) {
  return number = ("00"+number).slice(-2);
}
#parent {
  width: 100vw;
  height: 100vh;
  
  padding-bottom: 25vh;
}
#parent > div {
  padding-top: 25vh;
  
  -webkit-display: flex;
  display: flex;
  
  -webkit-flex-direction: row;
  flex-direction: row;
  
  -webkit-align-items: flex-start;
  align-items: flex-start;
  -webkit-justify-content: center;
  justify-content: center;
}

#items {
  width: 15vw;
  min-width: 110px;
  margin-right: 4vw;
  background-color: #222223;
  color: #eeeeef;
  border-radius: 4px;
  border: 2px solid black;
}

#items > span {
  box-sizing: border-box;
  display: block;
  padding: 5px;
  
  -webkit-transition: .2s background-color ease-in-out;
  transition: .2s background-color ease-in-out;
  
  text-align: center;
  
  width: 100%;
  
  border-radius: 4px;
}
#items > span:hover, #ticket p:hover {
  background-color: gray;
}
#items > span.selected, #ticket p.selected {
  background-color: #999999;
}
#ticket {
  -webkit-display: flex;
  display: flex;
  
  -webkit-flex-direction: row;
  flex-direction: row;
  
  margin-right: 4vw;
  
  color: #eeeeef;
}

#ticket p {
  margin: 1px;
  padding: 3px;
  width: 20px;
  text-align: center;
  background-color: #22222f;
  border: 2px solid black;
  border-radius: 3px;
}

#purchase {
  padding: 15px;
  padding-top: 6px;
  padding-bottom: 6px;
  
  background-color: #22222f;
  border: 2px solid black;
  border-radius: 3px;
  color: #eeeeef;
}
#purchase:active {
  background-color: gray;
}

#error {
  margin-top: 15px;
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<div id="parent" ng-app="app" ng-controller="MainCtrl">
  For testing hours-offset (If it's 6:00 setting this to 18 would simulate it being midnight): <input ng-model="hours_offset" type="number"></input>
  <div>
    <div id="items">
      <span ng-attr-class="{{selected_item===name ? 'selected' : ''}}" ng-repeat="(name, obj) in ::items track by $index" ng-click="selectItem(name)">{{::name}}<br></span>
    </div>
    <div id="ticket">
      <span ng-repeat="(ticket_index, val) in ::ticket">
        <p ng-attr-class="{{ticket[ticket_index]===$index ? 'selected' : ''}}" ng-repeat="nothing in ::nums track by $index" ng-click="ticket[ticket_index] = $index">{{::$index}}</p>
      </span>
    </div>
    <span id="purchase" ng-click="purchase()">Purchase</span>
  </div>
  <div id="error">{{error_msg}}</div>
  <table id="output">
    <tr ng-repeat="item in history track by $index">
      <td ng-repeat="(key, value) in item track by $index">{{value}}</td>
    </tr>
  </span>
</div>

csga5000
źródło
Witamy w PPCG. Chociaż GUI jest czymś, celem golfa jest napisanie możliwie najkrótszego programu. Ponieważ używasz JavaScript, możesz wziąć ciąg wejściowy jako parametr funkcji i zwrócić wynik. Powinieneś także usunąć niepotrzebne białe znaki i skrócić nazwy zmiennych. Dlaczego nie spojrzysz na inne pytania, aby dowiedzieć się, jak działa strona?
intrepidcoder,
@intrepidcoder Oczywiście później zminimalizujesz kod! Ale według scenariusza wydaje mi się, że konsola byłaby nieskuteczna bez klawiatury!
csga5000,
1
Zgodnie z zasadami opisanymi w naszym centrum pomocy , ten post nie jest aktualny. Wszystkie rozwiązania problemów powinny: [...] Być poważnym pretendentem do zwycięskich kryteriów w użyciu. Na przykład należy wziąć udział w turnieju golfa kodowego [.]
Dennis
Było to absurdalne uzasadnienie krótkiego kodu i nie miało nic wspólnego z rzeczywistym problemem. Łączny rozmiar trzech programów wynosi 4,51 KB. Jeśli nie spróbujesz go zmniejszyć, post prawdopodobnie zostanie usunięty.
intrepidcoder,
@intrepidcoder O tak! Zapomniałem o tym, było wiele ograniczeń xD. Kiedy mówisz ostatnią cyfrę, masz na myśli MSB lub LSB? Zgaduję LSB, ale chcę być pewien.
csga5000,