Created
November 26, 2012 02:30
-
-
Save sehe/4146271 to your computer and use it in GitHub Desktop.
2-Shipments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.o | |
main | |
*.sw[op] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Price 1=$2.00 Price 2=$7.00 Price 3=$8.50 | |
s New York 23 14 11 | |
s Miami 25 25 25 | |
s Los Angeles 40 13 17 | |
s Houston 100 30 10 | |
s Chicago 42 23 19 | |
s New York 0 0 15 | |
s Miami 13 17 21 | |
o Los Angeles 15 10 15 | |
o New York 12 24 8 | |
o Houston 75 45 10 | |
o Chicago 20 15 15 | |
o New York 15 0 0 | |
s Los Angeles 10 20 10 | |
s Houston 0 30 40 | |
o New York 15 15 25 | |
o Chicago 75 30 40 | |
s New York 20 15 20 | |
o Houston 10 20 10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by sehe on 11/26/12. | |
// Copyright (c) 2012 sehe. All rights reserved. | |
// | |
#include "logic.h" | |
#include <iostream> | |
#include <algorithm> | |
#include <cassert> | |
#include <map> | |
#include <iomanip> | |
using namespace std; | |
namespace /* anonymous */ | |
{ | |
typedef map<string, Warehouse> Warehouses; | |
typedef long Warehouse::* QtyProp; | |
///////////////////////////////////// | |
// IO primitives | |
std::ostream& operator<<(std::ostream& os, Warehouse const& a) | |
{ return os << a.quantity1 << '\t' << a.quantity2 << '\t' << a.quantity3; } | |
std::ostream& operator<<(std::ostream& os, Warehouses::value_type const& a) | |
{ return os << a.first << '\t' << a.second; } | |
std::ostream& operator<<(std::ostream& os, Card const& a) | |
{ return os << a.type << '\t' << a.location << '\t' << a.mutation1 << '\t' << a.mutation2 << '\t' << a.mutation3; } | |
///////////////////////////////////// | |
struct CompareByQty | |
{ | |
CompareByQty(QtyProp qfptr) : _qfptr(qfptr) {} | |
typedef Warehouses::value_type V; | |
bool operator()(V const& a, V const& b) const | |
{ return (a.second.*_qfptr) < (b.second.*_qfptr); } | |
QtyProp const _qfptr; | |
}; | |
pair<string, long> TryFillOrder(Warehouse& location, long& inorder, QtyProp qprop, Warehouses& tx) | |
{ | |
auto& stock = (location.*qprop); | |
auto fill = min(stock, inorder); | |
inorder -= fill; | |
stock -= fill; | |
if (inorder) | |
{ | |
auto it = max_element(tx.begin(), tx.end(), CompareByQty(qprop)); | |
auto& remote = it->second; | |
auto& remote_stock = remote.*qprop; | |
if (inorder<=remote_stock) | |
{ | |
auto back_order = make_pair(it->first, inorder); | |
// It would be rather nice to make this recursive: | |
// TryFillOrder(remote, inorder, qprop, tx); | |
inorder -= inorder; | |
remote_stock -= inorder; | |
return back_order; | |
} | |
} | |
return make_pair("", 0); | |
} | |
struct FilledOrder | |
{ | |
long fill1, fill2, fill3, back1, back2, back3; | |
bool usedBackorder() { return back1 || back2 || back3; } | |
bool empty() { return !usedBackorder() && !fill1 && !fill2 && !fill3; } | |
}; | |
FilledOrder FillOrder(Card const& order, Warehouses& warehouses) | |
{ | |
assert('o' == order.type); | |
auto rollback = warehouses; // prepare rollback | |
auto unfilled = order; | |
auto& from = warehouses[order.location]; | |
auto back1 = TryFillOrder(from, unfilled.mutation1, &Warehouse::quantity1, warehouses); | |
auto back2 = TryFillOrder(from, unfilled.mutation2, &Warehouse::quantity2, warehouses); | |
auto back3 = TryFillOrder(from, unfilled.mutation3, &Warehouse::quantity3, warehouses); | |
if (unfilled.mutation1 || unfilled.mutation2 || unfilled.mutation3) | |
{ | |
rollback.swap(warehouses); // rollback any changes | |
cout << "Order Unfilled\n"; | |
} else | |
{ | |
if (back1.second) | |
cout << back1.second << " of item 1 shipped from " << back1.first << " to " << order.location << "\n"; | |
if (back2.second) | |
cout << back2.second << " of item 2 shipped from " << back2.first << " to " << order.location << "\n"; | |
if (back3.second) | |
cout << back3.second << " of item 3 shipped from " << back3.first << " to " << order.location << "\n"; | |
return { | |
order.mutation1 - back1.second, | |
order.mutation2 - back2.second, | |
order.mutation3 - back3.second, | |
back1.second, back2.second, back3.second | |
}; | |
} | |
return {0}; | |
} | |
void ProcessShipment(Card const& shipment, Warehouses& warehouses) | |
{ | |
assert('s' == shipment.type); | |
cout << "-------- ProcessShipment\n" << shipment << '\n'; | |
auto& loc = warehouses[shipment.location]; | |
loc.quantity1 += shipment.mutation1; | |
loc.quantity2 += shipment.mutation2; | |
loc.quantity3 += shipment.mutation3; | |
cout << shipment.location << '\t' << loc << '\n'; | |
} | |
double ComputeBillTotal(FilledOrder const& filled, Pricing const& pricing) | |
{ | |
double total = 0; | |
total += pricing.price1 * filled.back1; | |
total += pricing.price2 * filled.back2; | |
total += pricing.price3 * filled.back3; | |
total *= 1.10; // 10% markup for backordered items | |
total += pricing.price1 * filled.fill1; | |
total += pricing.price2 * filled.fill2; | |
total += pricing.price3 * filled.fill3; | |
return total; | |
} | |
void ProcessOrder(Card const& order, Warehouses& stores, Pricing const& pricing) | |
{ | |
cout << "-------- ProcessOrder\n" << order << '\n'; | |
auto filled = FillOrder(order, stores); | |
if (!filled.empty()) | |
{ | |
if (filled.usedBackorder()) | |
for (auto& wh: stores) | |
std::cout << "New stock: " << wh << "\n"; | |
else | |
std::cout << "New stock: " << *stores.find(order.location) << "\n"; | |
double bill = ComputeBillTotal(filled, pricing); | |
std::cout << "Price of Order: $" << std::fixed << std::setprecision(2) << bill << "\n"; | |
} | |
} | |
} | |
void RunSimulation(vector<Card> const& cards, Pricing const& pricing) | |
{ | |
Warehouses stores; | |
for (const auto& card : cards) | |
switch (card.type) | |
{ | |
case 'o': ProcessOrder(card, stores, pricing); break; | |
case 's': ProcessShipment(card, stores); break; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by sehe on 11/26/12. | |
// Copyright (c) 2012 sehe. All rights reserved. | |
// | |
#pragma once | |
#include <string> | |
#include <vector> | |
struct Warehouse | |
{ | |
long quantity1; | |
long quantity2; | |
long quantity3; | |
}; | |
struct Pricing | |
{ | |
double price1; | |
double price2; | |
double price3; | |
}; | |
struct Card | |
{ | |
char type; | |
std::string location; | |
long mutation1; | |
long mutation2; | |
long mutation3; | |
}; | |
void RunSimulation(std::vector<Card> const& cards, Pricing const& pricing); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by sehe on 11/26/12. | |
// Copyright (c) 2012 sehe. All rights reserved. | |
// | |
#include "logic.h" | |
#include "parsing.h" | |
using namespace std; | |
int main() | |
{ | |
Pricing pricing; | |
vector<Card> cards; | |
if (ParseFile("cards.txt", pricing, cards)) | |
RunSimulation(cards, pricing); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all:main | |
main: parsing.o logic.o | |
CPPFLAGS+=-Wall | |
CPPFLAGS+=-g -O4 | |
CXXFLAGS+=$(CPPFLAGS) -std=c++0x | |
CPPFLAGS+=-I ~/custom/boost/ | |
%:%.cpp | |
$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by sehe on 11/26/12. | |
// Copyright (c) 2012 sehe. All rights reserved. | |
// | |
#include <boost/spirit/include/qi.hpp> | |
#include <boost/spirit/include/phoenix.hpp> | |
#include <boost/fusion/adapted.hpp> | |
#include <fstream> | |
#include "logic.h" | |
using namespace std; | |
BOOST_FUSION_ADAPT_STRUCT(Pricing , (double, price1)(double , price2)(double , price3)); | |
BOOST_FUSION_ADAPT_STRUCT(Warehouse, (long , quantity1)(long, quantity2)(long, quantity3)); | |
BOOST_FUSION_ADAPT_STRUCT(Card , (char , type)(string , location)(long , mutation1)(long, mutation2)(long, mutation3)); | |
namespace qi = boost::spirit::qi; | |
namespace phx = boost::phoenix; | |
bool ParseFile(string filename, Pricing& pricing, vector<Card>& cards) | |
{ | |
ifstream recordsFile(filename.c_str()); | |
recordsFile.unsetf(ios::skipws); | |
if (!recordsFile) { | |
cerr << "Could not open " << filename << endl; | |
return false; | |
} | |
typedef boost::spirit::istream_iterator It; | |
try | |
{ | |
using namespace qi; | |
using phx::ref; | |
It f(recordsFile), l; | |
{ | |
int index = 1; | |
auto fmt = "Price" > omit[uint_(ref(index)++)] > '=' > -lit('$') > double_; | |
if (!phrase_parse(f, l, fmt > fmt > fmt > +eol, blank, pricing)) | |
{ | |
cerr << "Can't parse pricing header\n"; | |
return false; | |
} | |
} | |
auto city = raw[eps >> "New York"|"Miami"|"Los Angeles"|"Houston"|"Chicago"]; | |
auto fmt = char_("so") >> city >> uint_ >> uint_ >> uint_; | |
if (!phrase_parse(f, l, *eol >> fmt % +eol >> *eol > eoi, blank, cards)) | |
{ | |
cout << "Couldn't parse card list (#" << cards.size()+1 << ")\n"; | |
return false; | |
} | |
} catch(qi::expectation_failure<It> const & e) | |
{ | |
string s; | |
istringstream iss(string(e.first, e.last)); | |
getline(iss, s); | |
cerr << "Unexpected input '" << s << "'\n"; | |
return false; | |
} | |
return true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by sehe on 11/26/12. | |
// Copyright (c) 2012 sehe. All rights reserved. | |
// | |
#pragma once | |
#include "logic.h" | |
bool ParseFile(std::string filename, Pricing& pricing, std::vector<Card>& cards); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment