Imported Java project files
This commit is contained in:
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
# KnappCC2017
|
||||
Knapp Coding Contest 2017
|
||||
|
||||
The master branch only contains the files provided by Knapp AG (not even decompressed).
|
||||
This branch only contains the provided project files for Java without any modifications.
|
Binary file not shown.
10001
input/containers.csv
Normal file
10001
input/containers.csv
Normal file
File diff suppressed because it is too large
Load Diff
101
input/products.csv
Normal file
101
input/products.csv
Normal file
@@ -0,0 +1,101 @@
|
||||
# code;(container-type;max-slot-quantity;)+
|
||||
PROD000001;Full;96;
|
||||
PROD000002;Full;55;Half;25;Quarter;10;
|
||||
PROD000003;Full;415;Half;207;Quarter;103;
|
||||
PROD000004;Full;48;
|
||||
PROD000005;Full;122;Half;60;Quarter;29;
|
||||
PROD000006;Full;55;Half;25;Quarter;10;
|
||||
PROD000007;Half;201;Quarter;100;
|
||||
PROD000008;Full;102;Half;51;
|
||||
PROD000009;Full;28;
|
||||
PROD000010;Full;127;Half;63;Quarter;31;
|
||||
PROD000011;Quarter;31;
|
||||
PROD000012;Full;198;Half;98;Quarter;48;
|
||||
PROD000013;Half;20;Quarter;9;
|
||||
PROD000014;Full;207;Half;103;Quarter;51;
|
||||
PROD000015;Full;51;Half;23;Quarter;9;
|
||||
PROD000016;Full;51;Half;23;Quarter;9;
|
||||
PROD000017;Half;96;Quarter;48;
|
||||
PROD000018;Full;396;Half;198;Quarter;99;
|
||||
PROD000019;Full;36;Half;18;Quarter;9;
|
||||
PROD000020;Full;40;Half;20;Quarter;10;
|
||||
PROD000021;Full;102;Half;51;
|
||||
PROD000022;Half;23;Quarter;9;
|
||||
PROD000023;Full;36;Half;18;Quarter;9;
|
||||
PROD000024;Full;48;
|
||||
PROD000025;Full;198;Half;98;
|
||||
PROD000026;Quarter;50;
|
||||
PROD000027;Full;29;
|
||||
PROD000028;Half;195;Quarter;97;
|
||||
PROD000029;Full;9;
|
||||
PROD000030;Full;130;Half;64;Quarter;31;
|
||||
PROD000031;Quarter;51;
|
||||
PROD000032;Full;192;Half;96;Quarter;48;
|
||||
PROD000033;Full;407;Half;203;Quarter;101;
|
||||
PROD000034;Full;139;Half;67;Quarter;31;
|
||||
PROD000035;Full;9;
|
||||
PROD000036;Full;99;
|
||||
PROD000037;Full;195;Half;97;Quarter;48;
|
||||
PROD000038;Full;49;
|
||||
PROD000039;Full;96;
|
||||
PROD000040;Full;61;Half;30;
|
||||
PROD000041;Full;42;Half;20;Quarter;9;
|
||||
PROD000042;Full;415;Half;205;Quarter;100;
|
||||
PROD000043;Full;396;Half;198;Quarter;99;
|
||||
PROD000044;Full;55;Half;25;Quarter;10;
|
||||
PROD000045;Full;46;Half;22;Quarter;10;
|
||||
PROD000046;Half;105;Quarter;50;
|
||||
PROD000047;Full;55;Half;25;Quarter;10;
|
||||
PROD000048;Full;50;
|
||||
PROD000049;Full;9;
|
||||
PROD000050;Full;20;Half;9;
|
||||
PROD000051;Full;400;Half;200;Quarter;100;
|
||||
PROD000052;Quarter;31;
|
||||
PROD000053;Full;207;Half;103;Quarter;51;
|
||||
PROD000054;Full;9;
|
||||
PROD000055;Full;36;Half;18;Quarter;9;
|
||||
PROD000056;Full;18;Half;9;
|
||||
PROD000057;Full;388;Half;194;Quarter;97;
|
||||
PROD000058;Quarter;9;
|
||||
PROD000059;Full;61;Half;28;
|
||||
PROD000060;Full;49;
|
||||
PROD000061;Full;10;
|
||||
PROD000062;Quarter;49;
|
||||
PROD000063;Full;387;Half;193;Quarter;96;
|
||||
PROD000064;Full;61;Half;30;
|
||||
PROD000065;Full;48;
|
||||
PROD000066;Full;42;Half;20;Quarter;9;
|
||||
PROD000067;Quarter;103;
|
||||
PROD000068;Full;120;Half;60;Quarter;30;
|
||||
PROD000069;Quarter;101;
|
||||
PROD000070;Full;202;Half;100;Quarter;49;
|
||||
PROD000071;Quarter;10;
|
||||
PROD000072;Full;192;Half;96;
|
||||
PROD000073;Full;120;Half;60;Quarter;30;
|
||||
PROD000074;Full;46;Half;22;Quarter;10;
|
||||
PROD000075;Full;101;
|
||||
PROD000076;Full;100;
|
||||
PROD000077;Full;119;Half;59;Quarter;29;
|
||||
PROD000078;Full;62;Half;31;
|
||||
PROD000079;Half;102;Quarter;51;
|
||||
PROD000080;Half;194;Quarter;97;
|
||||
PROD000081;Quarter;31;
|
||||
PROD000082;Full;112;Half;56;Quarter;28;
|
||||
PROD000083;Full;122;Half;60;Quarter;29;
|
||||
PROD000084;Full;390;Half;194;Quarter;96;
|
||||
PROD000085;Full;65;Half;30;
|
||||
PROD000086;Full;127;Half;61;Quarter;28;
|
||||
PROD000087;Half;18;Quarter;9;
|
||||
PROD000088;Full;116;Half;58;Quarter;29;
|
||||
PROD000089;Full;101;
|
||||
PROD000090;Full;115;Half;57;Quarter;28;
|
||||
PROD000091;Full;105;Half;50;
|
||||
PROD000092;Full;97;
|
||||
PROD000093;Full;20;Half;10;
|
||||
PROD000094;Full;116;Half;58;Quarter;29;
|
||||
PROD000095;Full;29;
|
||||
PROD000096;Full;9;
|
||||
PROD000097;Full;20;Half;10;
|
||||
PROD000098;Full;206;Half;102;Quarter;50;
|
||||
PROD000099;Half;21;Quarter;10;
|
||||
PROD000100;Full;10;
|
|
143
src/com/knapp/codingcontest/cc20170310/Main.java
Normal file
143
src/com/knapp/codingcontest/cc20170310/Main.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import com.knapp.codingcontest.cc20170310.data.ContainerType;
|
||||
import com.knapp.codingcontest.cc20170310.data.InputData;
|
||||
import com.knapp.codingcontest.cc20170310.solution.OptimizeStorage;
|
||||
import com.knapp.codingcontest.cc20170310.util.PrepareUpload;
|
||||
import com.knapp.codingcontest.cc20170310.warehouse.Warehouse;
|
||||
import com.knapp.codingcontest.cc20170310.warehouse.WarehouseInfos;
|
||||
|
||||
/**
|
||||
* ----------------------------------------------------------------------------
|
||||
* you may change any code you like
|
||||
* => but changing the output may lead to invalid results!
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
public class Main {
|
||||
public static void main(final String... args) throws Exception {
|
||||
System.out.println("KNAPP Coding Contest 2017: STARTING...");
|
||||
|
||||
System.out.println("# ... LOADING DATA ...");
|
||||
Warehouse warehouse = null;
|
||||
WarehouseInfos initialWarehouseInfos = null;
|
||||
|
||||
final InputData input = new InputData();
|
||||
input.readData();
|
||||
warehouse = new Warehouse(input);
|
||||
|
||||
System.out.println("# statistics before optimization");
|
||||
initialWarehouseInfos = warehouse.buildWarehouseInfos();
|
||||
Main.printWarehouseInfos(System.out, initialWarehouseInfos);
|
||||
|
||||
System.out.println("# ... OPTIMIZE STORAGE ...");
|
||||
final OptimizeStorage optimizeStorage = new OptimizeStorage(warehouse);
|
||||
optimizeStorage.optimizeStorage();
|
||||
|
||||
System.out.println("# ... WRITING OUTPUT/RESULT ...");
|
||||
System.out.println("# statistics after optimization");
|
||||
final WarehouseInfos warehouseInfos = warehouse.buildWarehouseInfos();
|
||||
//Main.printWarehouseInfos(System.out, warehouseInfos);
|
||||
Main.printWarehouseInfosDiff(System.out, initialWarehouseInfos, warehouseInfos);
|
||||
|
||||
PrepareUpload.createZipFile(warehouse);
|
||||
System.out
|
||||
.println(">>> Created " + PrepareUpload.FILENAME_WAREHOUSE_OPERATIONS + " & " + PrepareUpload.FILENAME_UPLOAD_ZIP);
|
||||
|
||||
System.out.println("KNAPP Coding Contest 2017: FINISHED");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public static final void printWarehouseInfos(final PrintStream out, final WarehouseInfos warehouseInfos) {
|
||||
out.println("# =============================================================================");
|
||||
out.println("# == WAREHOUSE INFOS ==========================================================");
|
||||
out.println("#");
|
||||
out.println(String.format("# total containers / slots"));
|
||||
for (final ContainerType ct : ContainerType.values()) {
|
||||
out.println(String.format("# %15s = %5d / %5d", ct, warehouseInfos.totalContainers_[ct.ordinal() + 1],
|
||||
warehouseInfos.totalSlots_[ct.ordinal() + 1]));
|
||||
}
|
||||
out.println(String.format("# %15s = %5d / %5d", "[TOTAL]", //
|
||||
warehouseInfos.totalContainers_[0], warehouseInfos.totalSlots_[0]));
|
||||
out.println("#");
|
||||
out.println(String.format("# containersAtWorkStation = %s", warehouseInfos.containersAtWorkStation));
|
||||
out.println(String.format("# numberOf gets / puts = %5d / %5d", warehouseInfos.numberOfGets,
|
||||
warehouseInfos.numberOfPuts));
|
||||
out.println(String.format("# numberOfMoves = %5d", warehouseInfos.numberOfMoves));
|
||||
out.println("#");
|
||||
out.println(String.format("# empty containers / slots"));
|
||||
for (final ContainerType ct : ContainerType.values()) {
|
||||
out.println(String.format("# %15s = %5d / %5d", ct, //
|
||||
warehouseInfos.emptyContainers_[ct.ordinal() + 1], warehouseInfos.emptySlots_[ct.ordinal() + 1]));
|
||||
}
|
||||
out.println(String.format("# %15s = %5d / %5d ( %.1f%% / %.1f%% )", "[TOTAL]", //
|
||||
warehouseInfos.emptyContainers_[0], warehouseInfos.emptySlots_[0], //
|
||||
((double) warehouseInfos.emptyContainers_[0] / warehouseInfos.totalContainers_[0]) * 100, //
|
||||
((double) warehouseInfos.emptySlots_[0] / warehouseInfos.totalSlots_[0]) * 100));
|
||||
out.println("#");
|
||||
out.println("# =============================================================================");
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
|
||||
public static final void printWarehouseInfosDiff(final PrintStream out, final WarehouseInfos warehouseInfos1,
|
||||
final WarehouseInfos warehouseInfos2) {
|
||||
out.println("# =============================================================================");
|
||||
out.println("# -- DIFFS --------------------------------------------------------------------");
|
||||
out.println("#");
|
||||
out.println(String.format("# %-16s | %-14s | %-14s |", "Empty", "Containers", "Slots"));
|
||||
out.println(String.format("# %16s | %14s | %14s |", "", "", ""));
|
||||
for (final ContainerType ct : ContainerType.values()) {
|
||||
out.println(String.format("# %10s | %5d %8s | %5d %8s |", ct, //
|
||||
warehouseInfos2.emptyContainers_[ct.ordinal() + 1], //
|
||||
Main.fs(warehouseInfos2.emptyContainers_[ct.ordinal() + 1] - warehouseInfos1.emptyContainers_[ct.ordinal() + 1]), //
|
||||
warehouseInfos2.emptySlots_[ct.ordinal() + 1], //
|
||||
Main.fs(warehouseInfos2.emptySlots_[ct.ordinal() + 1] - warehouseInfos1.emptySlots_[ct.ordinal() + 1])));
|
||||
}
|
||||
out.println(String.format("# %16s | %14s | %14s |", "", "", ""));
|
||||
out.println(String.format("# %10s | %5d %8s | %5d %8s |", "[TOTAL]", //
|
||||
warehouseInfos2.emptyContainers_[0], //
|
||||
Main.fs(warehouseInfos2.emptyContainers_[0] - warehouseInfos1.emptyContainers_[0]), //
|
||||
warehouseInfos2.emptySlots_[0], //
|
||||
Main.fs(warehouseInfos2.emptySlots_[0] - warehouseInfos1.emptySlots_[0])));
|
||||
out.println("#");
|
||||
out.println("# ==> SCORE: " + Main.getScore(warehouseInfos1, warehouseInfos2) + " (exclusive upload-time)");
|
||||
out.println("#");
|
||||
out.println("# =============================================================================");
|
||||
}
|
||||
|
||||
private static int getScore(final WarehouseInfos wi1, final WarehouseInfos wi2) {
|
||||
int score = 0;
|
||||
for (final ContainerType type : ContainerType.values()) {
|
||||
score += ((wi2.emptySlots_[type.ordinal() + 1] - wi1.emptySlots_[type.ordinal() + 1]) * (4 / type.getNumberOfSlots()));
|
||||
}
|
||||
score += 2 * (wi2.emptyContainers_[0] - wi1.emptyContainers_[0]);
|
||||
return score;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private static String fs(final int value) {
|
||||
if (value <= 0) {
|
||||
return "(" + value + ")";
|
||||
}
|
||||
return "(+" + value + ")";
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
}
|
88
src/com/knapp/codingcontest/cc20170310/data/Container.java
Normal file
88
src/com/knapp/codingcontest/cc20170310/data/Container.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Container {
|
||||
// ----------------------------------------------------------------------------
|
||||
// ............................................................................
|
||||
|
||||
private final String code;
|
||||
private final ContainerType type;
|
||||
private final ContainerSlot[] slots;
|
||||
private final List<ContainerSlot> slots_;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
protected Container(final String code, final ContainerType type) {
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
slots = new ContainerSlot[type.getNumberOfSlots()];
|
||||
for (int i = 0; i < slots.length; i++) {
|
||||
slots[i] = new ContainerSlot(this, i);
|
||||
}
|
||||
slots_ = Collections.unmodifiableList(Arrays.asList(slots));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final String[] slotStrings = new String[slots.length];
|
||||
for (int s = 0; s < slots.length; s++) {
|
||||
slotStrings[s] = slots[s].isEmpty() ? "<empty>" : (slots[s].getProduct().getCode() + "#" + slots[s].getQuantity());
|
||||
}
|
||||
return "Container[code=" + code + ", type=" + type + "]{" + Arrays.toString(slotStrings) + "}";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public final String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public final ContainerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
for (final ContainerSlot slot : slots) {
|
||||
if (!slot.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<ContainerSlot> getEmptySlots() {
|
||||
final List<ContainerSlot> emptySlots = new ArrayList<ContainerSlot>();
|
||||
for (final ContainerSlot slot : slots) {
|
||||
if (slot.isEmpty()) {
|
||||
emptySlots.add(slot);
|
||||
}
|
||||
}
|
||||
return emptySlots;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public List<ContainerSlot> getSlots() {
|
||||
return Collections.unmodifiableList(slots_);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.data;
|
||||
|
||||
public class ContainerSlot {
|
||||
private final Container container;
|
||||
private final int index;
|
||||
private Product product;
|
||||
private int quantity;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ContainerSlot(final Container container, final int index) {
|
||||
this.container = container;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public Container getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isEmpty()) {
|
||||
return "ContainerSlot[]";
|
||||
}
|
||||
return "ContainerSlot[product=" + product + ", quantity=" + quantity + "]";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public boolean isEmpty() {
|
||||
return product == null;
|
||||
}
|
||||
|
||||
public Product getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
// should only be called internal!!! otherwise you could tamper with the result
|
||||
// (Warehouse.apply(moveItems), InputData.readContainers())
|
||||
|
||||
public void _setProduct(final Product product) {
|
||||
this.product = product;
|
||||
}
|
||||
|
||||
public void _setQuantity(final int quantity) {
|
||||
this.quantity = quantity;
|
||||
if (quantity == 0) {
|
||||
product = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.data;
|
||||
|
||||
public enum ContainerType {
|
||||
Full(1), //
|
||||
Half(2), //
|
||||
Quarter(4), //
|
||||
;
|
||||
|
||||
private final int slots;
|
||||
|
||||
private ContainerType(final int slots) {
|
||||
this.slots = slots;
|
||||
}
|
||||
|
||||
public int getNumberOfSlots() {
|
||||
return slots;
|
||||
}
|
||||
}
|
173
src/com/knapp/codingcontest/cc20170310/data/InputData.java
Normal file
173
src/com/knapp/codingcontest/cc20170310/data/InputData.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.data;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class InputData {
|
||||
private static final String PATH_INPUT_DATA;
|
||||
static {
|
||||
try {
|
||||
PATH_INPUT_DATA = new File("./input").getCanonicalPath();
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private final String dataPath;
|
||||
private final List<Product> products = new ArrayList<Product>();
|
||||
private final List<Container> containers = new ArrayList<Container>();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public InputData() {
|
||||
this(InputData.PATH_INPUT_DATA);
|
||||
}
|
||||
|
||||
public InputData(final String dataPath) {
|
||||
this.dataPath = dataPath;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InputData@" + dataPath + "[" + products + ",\n " + containers + "]";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public void readData() throws IOException {
|
||||
readProducts();
|
||||
readContainers();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public final List<Product> getProducts() {
|
||||
return Collections.unmodifiableList(products);
|
||||
}
|
||||
|
||||
public final List<Container> getContainers() {
|
||||
return Collections.unmodifiableList(containers);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private void readProducts() throws IOException {
|
||||
final Reader fr = new FileReader(fullFileName("products.csv"));
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(fr);
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
line = line.trim();
|
||||
if ("".equals(line) || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
// code;(container-type;max-slot-quantity;)+
|
||||
final String[] columns = splitCsv(line);
|
||||
final String code = columns[0];
|
||||
final Product product = new Product(code);
|
||||
for (int i = 1; i < columns.length; i += 2) {
|
||||
final ContainerType ct = ContainerType.valueOf(columns[i + 0]);
|
||||
final int ctmax = Integer.parseInt(columns[i + 1]);
|
||||
product.setMaxQuantity(ct, ctmax);
|
||||
}
|
||||
products.add(product);
|
||||
}
|
||||
} finally {
|
||||
close(reader);
|
||||
close(fr);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private void readContainers() throws IOException {
|
||||
final Reader fr = new FileReader(fullFileName("containers.csv"));
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(fr);
|
||||
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
|
||||
line = line.trim();
|
||||
if ("".equals(line) || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
// code;type(;product;quantity>0)*{#lots4type};
|
||||
final String[] columns = splitCsv(line);
|
||||
final String code = columns[0];
|
||||
final ContainerType type = ContainerType.valueOf(columns[1]);
|
||||
final Container container = new Container(code, type);
|
||||
for (int i = 2, s = 0; i < columns.length; i += 2, s++) {
|
||||
final String productCode = columns[i + 0];
|
||||
if (!"".equals(productCode)) {
|
||||
final Product product = findProductByCode(productCode);
|
||||
final int quantity = Integer.parseInt(columns[i + 1]);
|
||||
container.getSlots().get(s)._setProduct(product);
|
||||
container.getSlots().get(s)._setQuantity(quantity);
|
||||
}
|
||||
}
|
||||
containers.add(container);
|
||||
}
|
||||
} finally {
|
||||
close(reader);
|
||||
close(fr);
|
||||
}
|
||||
}
|
||||
|
||||
private Product findProductByCode(final String productCode) {
|
||||
for (final Product product : products) {
|
||||
if (productCode.equals(product.getCode())) {
|
||||
return product;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("no product found for code=" + productCode);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
protected File fullFileName(final String fileName) {
|
||||
final String fullFileName = dataPath + File.separator + fileName;
|
||||
return new File(fullFileName);
|
||||
}
|
||||
|
||||
protected void close(final Closeable closeable) {
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (final IOException exception) {
|
||||
exception.printStackTrace(System.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
protected String[] splitCsv(final String line) {
|
||||
return line.split(";");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ............................................................................
|
||||
}
|
59
src/com/knapp/codingcontest/cc20170310/data/Product.java
Normal file
59
src/com/knapp/codingcontest/cc20170310/data/Product.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.data;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Product {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private final String code;
|
||||
private final Map<ContainerType, Integer> maxQuantities;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
protected Product(final String code) {
|
||||
this.code = code;
|
||||
maxQuantities = new EnumMap<ContainerType, Integer>(ContainerType.class);
|
||||
for (final ContainerType t : ContainerType.values()) {
|
||||
maxQuantities.put(t, Integer.valueOf(0));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Product[code=" + code + ", maxQuantities=" + maxQuantities + "]";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public final String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public final int getMaxQuantity(final ContainerType type) {
|
||||
return maxQuantities.get(type).intValue();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
protected void setMaxQuantity(final ContainerType type, final int maxQuantity) {
|
||||
maxQuantities.put(type, Integer.valueOf(maxQuantity));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ............................................................................
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.solution;
|
||||
|
||||
import com.knapp.codingcontest.cc20170310.warehouse.Warehouse;
|
||||
|
||||
/**
|
||||
* This is the code YOU have to provide
|
||||
*
|
||||
* @param warehouseOperations all the operations you should need
|
||||
*/
|
||||
public class OptimizeStorage {
|
||||
/**
|
||||
* TODO: Your name
|
||||
*/
|
||||
public static final String PARTICIPANT_NAME;
|
||||
|
||||
/**
|
||||
* TODO: The Id of your institute - please refer to the handout
|
||||
*/
|
||||
public static final String PARTICIPANT_INSTITUTION;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private final Warehouse warehouse;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public OptimizeStorage(final Warehouse warehouse) {
|
||||
this.warehouse = warehouse;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public void optimizeStorage() {
|
||||
System.out.println("### Your output starts here");
|
||||
|
||||
// ==> CODE YOUR SOLUTION HERE !!!");
|
||||
|
||||
System.out.println("### Your output stops here");
|
||||
}
|
||||
}
|
250
src/com/knapp/codingcontest/cc20170310/util/PrepareUpload.java
Normal file
250
src/com/knapp/codingcontest/cc20170310/util/PrepareUpload.java
Normal file
@@ -0,0 +1,250 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import com.knapp.codingcontest.cc20170310.solution.OptimizeStorage;
|
||||
import com.knapp.codingcontest.cc20170310.warehouse.Warehouse;
|
||||
import com.knapp.codingcontest.cc20170310.warehouse.WarehouseOperation;
|
||||
|
||||
/**
|
||||
* Helper class to create zip for upload
|
||||
*/
|
||||
public final class PrepareUpload {
|
||||
private static final String PATH_OUTPUT;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ............................................................................
|
||||
|
||||
static {
|
||||
try {
|
||||
PATH_OUTPUT = new File("./").getCanonicalPath();
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
public static final String FILENAME_WAREHOUSE_OPERATIONS = "warehouse-operations.csv";
|
||||
public static final String FILENAME_META_PROPERTIES = "kcc2017.properties";
|
||||
public static final String FILENAME_UPLOAD_ZIP = "upload2017.zip";
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private PrepareUpload() {
|
||||
// avoid construction
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create uploadable zip file
|
||||
* @param warehouse.
|
||||
* @param input
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void createZipFile(final Warehouse warehouse) throws Exception {
|
||||
final File basedir = new File(PrepareUpload.PATH_OUTPUT);
|
||||
final String zipFileName = PrepareUpload.PATH_OUTPUT + File.separator + PrepareUpload.FILENAME_UPLOAD_ZIP;
|
||||
final File zipFile = new File(zipFileName);
|
||||
if (zipFile.exists()) {
|
||||
zipFile.delete();
|
||||
}
|
||||
|
||||
ZipOutputStream archive = null;
|
||||
try {
|
||||
archive = new ZipOutputStream(new FileOutputStream(zipFile));
|
||||
|
||||
final String resultsFileName = PrepareUpload.PATH_OUTPUT + File.separator + PrepareUpload.FILENAME_WAREHOUSE_OPERATIONS;
|
||||
PrepareUpload.storeResult(resultsFileName, warehouse.result());
|
||||
PrepareUpload.addFile(archive, basedir, new File(resultsFileName));
|
||||
|
||||
final String propertiesFileName = PrepareUpload.PATH_OUTPUT + File.separator + PrepareUpload.FILENAME_META_PROPERTIES;
|
||||
PrepareUpload.addInputStream(archive, basedir, new File(propertiesFileName), PrepareUpload.properties());
|
||||
|
||||
PrepareUpload.add(archive, basedir, new File("src"));
|
||||
} finally {
|
||||
if (archive != null) {
|
||||
archive.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void storeResult(final String resultsFileName, final Iterable<WarehouseOperation> result) throws IOException {
|
||||
final Writer fw = new FileWriter(resultsFileName);
|
||||
BufferedWriter writer = null;
|
||||
try {
|
||||
writer = new BufferedWriter(fw);
|
||||
for (final WarehouseOperation warehouseOperation : result) {
|
||||
writer.append(warehouseOperation.toResultString());
|
||||
writer.newLine();
|
||||
}
|
||||
} finally {
|
||||
PrepareUpload.close(writer);
|
||||
PrepareUpload.close(fw);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private static void add(final ZipOutputStream archive, final File basedir, final File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
if (PrepareUpload.shouldAddDirectory(basedir, file)) {
|
||||
PrepareUpload.addDirectory(archive, basedir, file);
|
||||
}
|
||||
} else {
|
||||
if (PrepareUpload.shouldAddFile(basedir, file)) {
|
||||
PrepareUpload.addFile(archive, basedir, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
|
||||
private static boolean shouldAddDirectory(final File basedir, final File file) {
|
||||
return !"META-INF".equals(file.getName());
|
||||
}
|
||||
|
||||
private static boolean shouldAddFile(final File basedir, final File file) {
|
||||
return !file.getName().equals(PrepareUpload.FILENAME_UPLOAD_ZIP);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private static void addDirectory(final ZipOutputStream archive, final File basedir, final File file) throws IOException {
|
||||
if (!basedir.equals(file)) {
|
||||
String name = file.getAbsolutePath().replace("\\", "/");
|
||||
if (!name.isEmpty()) {
|
||||
if (!name.endsWith("/")) {
|
||||
name += "/";
|
||||
}
|
||||
|
||||
final ZipEntry entry = new ZipEntry(name.substring(basedir.getAbsolutePath().length() + 1));
|
||||
entry.setTime(file.lastModified());
|
||||
archive.putNextEntry(entry);
|
||||
archive.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
for (final File nestedFile : file.listFiles()) {
|
||||
PrepareUpload.add(archive, basedir, nestedFile);
|
||||
}
|
||||
}
|
||||
|
||||
// ............................................................................
|
||||
|
||||
private static void addFile(final ZipOutputStream archive, final File basedir, final File file) throws IOException,
|
||||
FileNotFoundException {
|
||||
BufferedInputStream in = null;
|
||||
try {
|
||||
final ZipEntry entry = new ZipEntry(file.getAbsolutePath().replace("\\", "/")
|
||||
.substring(basedir.getAbsolutePath().length() + 1));
|
||||
entry.setTime(file.lastModified());
|
||||
archive.putNextEntry(entry);
|
||||
|
||||
in = new BufferedInputStream(new FileInputStream(file));
|
||||
PrepareUpload.copyContent(in, archive);
|
||||
|
||||
archive.closeEntry();
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addInputStream(final ZipOutputStream archive, final File basedir, final File file,
|
||||
final InputStream inputStream) throws IOException, FileNotFoundException {
|
||||
BufferedInputStream in = null;
|
||||
try {
|
||||
final ZipEntry entry = new ZipEntry(file.getAbsolutePath().replace("\\", "/")
|
||||
.substring(basedir.getAbsolutePath().length() + 1));
|
||||
entry.setTime(file.lastModified());
|
||||
archive.putNextEntry(entry);
|
||||
|
||||
in = new BufferedInputStream(inputStream);
|
||||
PrepareUpload.copyContent(in, archive);
|
||||
|
||||
archive.closeEntry();
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private static void copyContent(final InputStream in, final OutputStream out) throws IOException {
|
||||
final byte[] buffer = new byte[8192];
|
||||
for (int count = in.read(buffer); count >= 0; count = in.read(buffer)) {
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private static InputStream properties() throws Exception {
|
||||
BufferedWriter writer = null;
|
||||
try {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
writer = new BufferedWriter(new OutputStreamWriter(baos));
|
||||
writer.write("# -*- conf-javaprop -*-");
|
||||
writer.newLine();
|
||||
writer.write(String.format("participant = %s %s", OptimizeStorage.PARTICIPANT_INSTITUTION.trim(),
|
||||
OptimizeStorage.PARTICIPANT_NAME.trim()));
|
||||
writer.newLine();
|
||||
writer.write("technology = java");
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private static void close(final Closeable closeable) {
|
||||
if (closeable != null) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (final IOException exception) {
|
||||
exception.printStackTrace(System.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class ContainerMaxGetExceededException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ContainerMaxGetExceededException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class ContainerNotAtWorkStationException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ContainerNotAtWorkStationException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class ContainerNotInStorageException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ContainerNotInStorageException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class DestinationFillingExceededException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DestinationFillingExceededException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class ProductMismatchException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ProductMismatchException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class SourceFillingExhaustedException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SourceFillingExhaustedException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
190
src/com/knapp/codingcontest/cc20170310/warehouse/Warehouse.java
Normal file
190
src/com/knapp/codingcontest/cc20170310/warehouse/Warehouse.java
Normal file
@@ -0,0 +1,190 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.knapp.codingcontest.cc20170310.data.Container;
|
||||
import com.knapp.codingcontest.cc20170310.data.ContainerSlot;
|
||||
import com.knapp.codingcontest.cc20170310.data.InputData;
|
||||
import com.knapp.codingcontest.cc20170310.data.Product;
|
||||
|
||||
public class Warehouse {
|
||||
// ----------------------------------------------------------------------------
|
||||
// -- DO NOT CHANGE THESE -----------------------------------------------------
|
||||
// (your result will be evaluated on the server with these settings)
|
||||
|
||||
public static final int WORK_STATION_CAPACITY = 5;
|
||||
public static final int CONTAINER_MAX_GET = 5000;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
final InputData input;
|
||||
//
|
||||
private final Map<String, Container> workStation;
|
||||
//
|
||||
int currentNumberOfGets = 0;
|
||||
int currentNumberOfMoves = 0;
|
||||
int currentNumberOfPuts = 0;
|
||||
private final List<WarehouseOperation> result = new LinkedList<WarehouseOperation>();
|
||||
|
||||
private WarehouseInfos warehouseInfos;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public Warehouse(final InputData input) {
|
||||
this.input = input;
|
||||
workStation = new HashMap<String, Container>();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// -- query & statistics operations
|
||||
|
||||
public final List<Container> getAllContainers() {
|
||||
return input.getContainers();
|
||||
}
|
||||
|
||||
public final List<Container> getContainersAtWorkStation() {
|
||||
final List<Container> containers = new ArrayList<Container>(Warehouse.WORK_STATION_CAPACITY);
|
||||
for (final Container c : workStation.values()) {
|
||||
containers.add(c);
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
||||
public final List<Container> getContainersInStorage() {
|
||||
final List<Container> containers = new ArrayList<Container>(getAllContainers());
|
||||
containers.removeAll(getContainersAtWorkStation());
|
||||
return containers;
|
||||
}
|
||||
|
||||
public final int getRemainingMovesToWorkStation() {
|
||||
return Warehouse.CONTAINER_MAX_GET - currentNumberOfGets;
|
||||
}
|
||||
|
||||
//
|
||||
public final WarehouseInfos buildWarehouseInfos() {
|
||||
if (warehouseInfos == null) {
|
||||
warehouseInfos = new WarehouseInfos(this);
|
||||
}
|
||||
return warehouseInfos;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public final Iterable<WarehouseOperation> result() {
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public void moveToWorkStation(final Container container) throws IllegalArgumentException, ContainerNotInStorageException,
|
||||
WorkStationCapcityExceededException, ContainerMaxGetExceededException {
|
||||
if (container == null) {
|
||||
throw new IllegalArgumentException("container must not be <null>");
|
||||
}
|
||||
|
||||
result.add(new WarehouseOperation.GetContainer(container));
|
||||
|
||||
if (workStation.containsKey(container.getCode())) {
|
||||
throw new ContainerNotInStorageException("container is already at work-station: " + container);
|
||||
}
|
||||
|
||||
if (workStation.size() >= Warehouse.WORK_STATION_CAPACITY) {
|
||||
throw new WorkStationCapcityExceededException("containers at workStation are limited to: "
|
||||
+ Warehouse.WORK_STATION_CAPACITY + " => @workStation=" + workStation.values());
|
||||
}
|
||||
|
||||
if (currentNumberOfGets >= Warehouse.CONTAINER_MAX_GET) {
|
||||
throw new ContainerMaxGetExceededException("gets are limited to: " + Warehouse.CONTAINER_MAX_GET);
|
||||
}
|
||||
|
||||
currentNumberOfGets++;
|
||||
|
||||
workStation.put(container.getCode(), container);
|
||||
}
|
||||
|
||||
public void transferItems(final ContainerSlot source, final ContainerSlot destination, final int quantity)
|
||||
throws IllegalArgumentException, ContainerNotAtWorkStationException, SourceFillingExhaustedException,
|
||||
ProductMismatchException, DestinationFillingExceededException {
|
||||
warehouseInfos = null;
|
||||
if ((source == null) || (destination == null)) {
|
||||
throw new IllegalArgumentException("incomplete move (source or dest is <null>)");
|
||||
}
|
||||
final WarehouseOperation.MoveItems moveItems = new WarehouseOperation.MoveItems(source, destination, quantity);
|
||||
|
||||
if (quantity <= 0) {
|
||||
throw new IllegalArgumentException("quantity (must be > 0): " + moveItems);
|
||||
}
|
||||
if (source.isEmpty()) {
|
||||
throw new IllegalArgumentException("no products at source: " + moveItems);
|
||||
}
|
||||
|
||||
if (!workStation.containsKey(moveItems.source.getContainer().getCode())) {
|
||||
throw new ContainerNotAtWorkStationException("source container not at workStation: " + moveItems + " => @workStation="
|
||||
+ workStation.values());
|
||||
}
|
||||
if (!workStation.containsKey(moveItems.destination.getContainer().getCode())) {
|
||||
throw new ContainerNotAtWorkStationException("destination container not at workStation: " + moveItems
|
||||
+ " => @workStation=" + workStation.values());
|
||||
}
|
||||
|
||||
final Product sourceProduct = source.getProduct();
|
||||
final Product destinationProduct = destination.getProduct();
|
||||
|
||||
if (source.getQuantity() < quantity) {
|
||||
throw new SourceFillingExhaustedException("can't take #" + quantity + " from source: " + moveItems);
|
||||
}
|
||||
if (!destination.isEmpty()) {
|
||||
if (sourceProduct != destinationProduct) {
|
||||
throw new ProductMismatchException("mismatching products: " + moveItems.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if ((destination.getQuantity() + quantity) > sourceProduct.getMaxQuantity(destination.getContainer().getType())) {
|
||||
throw new DestinationFillingExceededException("can't put #" + quantity + " to destination: " + moveItems
|
||||
+ " => max/slot=" + sourceProduct.getMaxQuantity(destination.getContainer().getType()));
|
||||
}
|
||||
|
||||
//
|
||||
source._setQuantity(source.getQuantity() - quantity);
|
||||
destination._setQuantity(destination.getQuantity() + quantity);
|
||||
destination._setProduct(sourceProduct);
|
||||
|
||||
result.add(moveItems);
|
||||
currentNumberOfMoves++;
|
||||
}
|
||||
|
||||
public void moveToStorage(final Container container) throws IllegalArgumentException, ContainerNotAtWorkStationException {
|
||||
if (container == null) {
|
||||
throw new IllegalArgumentException("container must not be <null>");
|
||||
}
|
||||
|
||||
result.add(new WarehouseOperation.PutContainer(container));
|
||||
|
||||
if (!workStation.containsKey(container.getCode())) {
|
||||
throw new ContainerNotAtWorkStationException("container not at workStation: " + container);
|
||||
}
|
||||
|
||||
currentNumberOfPuts++;
|
||||
|
||||
workStation.remove(container.getCode());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.knapp.codingcontest.cc20170310.data.Container;
|
||||
import com.knapp.codingcontest.cc20170310.data.ContainerType;
|
||||
|
||||
public class WarehouseInfos implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final int[] totalContainers_;
|
||||
public final int[] totalSlots_;
|
||||
public final transient List<Container> containersAtWorkStation;
|
||||
//
|
||||
public final int numberOfGets;
|
||||
public final int numberOfPuts;
|
||||
public final int numberOfMoves;
|
||||
//
|
||||
public final int[] emptyContainers_;
|
||||
public final int[] emptySlots_;
|
||||
public final Throwable throwable;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public WarehouseInfos(final Warehouse warehouse) {
|
||||
this(warehouse, null);
|
||||
}
|
||||
|
||||
public WarehouseInfos(final Warehouse warehouse, final Throwable throwable) {
|
||||
totalContainers_ = countTotalContainers(warehouse);
|
||||
totalSlots_ = countTotalSlots(warehouse);
|
||||
containersAtWorkStation = warehouse.getContainersAtWorkStation();
|
||||
numberOfGets = warehouse.currentNumberOfGets;
|
||||
numberOfPuts = warehouse.currentNumberOfPuts;
|
||||
numberOfMoves = warehouse.currentNumberOfMoves;
|
||||
emptyContainers_ = countEmptyContainers(warehouse);
|
||||
emptySlots_ = countEmptySlots(warehouse);
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WarehouseInfos[totalContainers=" + Arrays.toString(totalContainers_) + ", totalSlots="
|
||||
+ Arrays.toString(totalSlots_) //
|
||||
+ ", containersAtWorkStation=" + containersAtWorkStation //
|
||||
+ ", numberOfGets=" + numberOfGets + ", numberOfPuts=" + numberOfPuts //
|
||||
+ ", numberOfMoves=" + numberOfMoves //
|
||||
+ ", emptyContainers=" + Arrays.toString(emptyContainers_) + ", emptySlots=" + Arrays.toString(emptySlots_) //
|
||||
+ "]";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
private int[] countTotalContainers(final Warehouse warehouse) {
|
||||
final int[] totalContainers = new int[ContainerType.values().length + 1];
|
||||
for (final Container container : warehouse.input.getContainers()) {
|
||||
totalContainers[0]++;
|
||||
totalContainers[container.getType().ordinal() + 1]++;
|
||||
}
|
||||
return totalContainers;
|
||||
}
|
||||
|
||||
private int[] countTotalSlots(final Warehouse warehouse) {
|
||||
final int[] totalSlots = new int[ContainerType.values().length + 1];
|
||||
for (final Container container : warehouse.input.getContainers()) {
|
||||
totalSlots[0] += container.getType().getNumberOfSlots();
|
||||
totalSlots[container.getType().ordinal() + 1] += container.getType().getNumberOfSlots();
|
||||
}
|
||||
return totalSlots;
|
||||
}
|
||||
|
||||
private int[] countEmptyContainers(final Warehouse warehouse) {
|
||||
final int[] emptyContainers = new int[ContainerType.values().length + 1];
|
||||
for (final Container container : warehouse.input.getContainers()) {
|
||||
if (container.isEmpty()) {
|
||||
emptyContainers[0]++;
|
||||
emptyContainers[container.getType().ordinal() + 1]++;
|
||||
}
|
||||
}
|
||||
return emptyContainers;
|
||||
}
|
||||
|
||||
private int[] countEmptySlots(final Warehouse warehouse) {
|
||||
final int[] emptySlots = new int[ContainerType.values().length + 1];
|
||||
for (final Container container : warehouse.input.getContainers()) {
|
||||
for (int s = 0; s < container.getType().getNumberOfSlots(); s++) {
|
||||
if (container.getSlots().get(s).isEmpty()) {
|
||||
emptySlots[0]++;
|
||||
emptySlots[container.getType().ordinal() + 1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return emptySlots;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
import com.knapp.codingcontest.cc20170310.data.Container;
|
||||
import com.knapp.codingcontest.cc20170310.data.ContainerSlot;
|
||||
|
||||
public abstract class WarehouseOperation {
|
||||
private final String toResultString;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
protected WarehouseOperation(final Object... args) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(getClass().getSimpleName()).append(";");
|
||||
for (final Object arg : args) {
|
||||
sb.append(arg).append(";");
|
||||
}
|
||||
toResultString = sb.toString();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public final String toResultString() {
|
||||
return toResultString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toResultString();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
public static final class GetContainer extends WarehouseOperation {
|
||||
public GetContainer(final Container container) {
|
||||
super(container.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PutContainer extends WarehouseOperation {
|
||||
public PutContainer(final Container container) {
|
||||
super(container.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class MoveItems extends WarehouseOperation {
|
||||
public final ContainerSlot source;
|
||||
public final ContainerSlot destination;
|
||||
public final int quantity;
|
||||
|
||||
public MoveItems(final ContainerSlot source, final ContainerSlot destination, final int quantity) {
|
||||
super(source.getContainer().getCode(), source.getIndex(), destination.getContainer().getCode(), destination.getIndex(),
|
||||
quantity);
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MoveItems[source=" + source.getContainer().getCode() + "/" + source.getIndex() + ", destination="
|
||||
+ destination.getContainer().getCode() + "/" + destination.getIndex() + ", quantity=" + quantity + "]";
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/* -*- java -*- ************************************************************************** *
|
||||
*
|
||||
* Copyright (C) KNAPP AG
|
||||
*
|
||||
* The copyright to the computer program(s) herein is the property
|
||||
* of Knapp. The program(s) may be used and/or copied only with
|
||||
* the written permission of Knapp or in accordance with the
|
||||
* terms and conditions stipulated in the agreement/contract under
|
||||
* which the program(s) have been supplied.
|
||||
*
|
||||
* *************************************************************************************** */
|
||||
|
||||
package com.knapp.codingcontest.cc20170310.warehouse;
|
||||
|
||||
public class WorkStationCapcityExceededException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public WorkStationCapcityExceededException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user