mirror of
https://github.com/Xevion/contest.git
synced 2025-12-06 05:14:41 -06:00
feb 2015 problem 11 and 12
This commit is contained in:
15
uil/aplus-february-2015/11/Spending.MD
Normal file
15
uil/aplus-february-2015/11/Spending.MD
Normal file
@@ -0,0 +1,15 @@
|
||||
# Spending
|
||||
|
||||
Run my solution on **[repl.it](https://repl.it/@Xevion/A-Computer-Science-February-2015-Spending-partial)!**
|
||||
|
||||
At first, this problem disguises itself as being relatively easy, once you setup all the data that you need to import. Other than understanding you have 'multiple spending limits' (whatever this means in the real world), the problem is relatively easy, and a quick glance over the questions one needs to solve and output, it makes sense.
|
||||
|
||||
However, this problem has a MASSIVE gotcha that stumps all who attempt to solve it, as it requires knowledge of **Combinatorics**, a mathematical area useful for generating all possible states a structure (typically a array or tree) can be in. Here, it's seen in Question 4, where you must identify the maximum amount of money one could spend.
|
||||
|
||||
Without thinking, it would seem that it's similar to the rest, and can be implemented relatively easy, and I did too, but test cases *should* fail quickly, and yield one questioning their code.
|
||||
|
||||
Here's an example of how it might go wrong, a implementation that essentially buys the most expensive items first... With three items with three distinct worths, $40, $30, and $20, with a total budget of $50, one can quickly notice that purchasing the two items worth $30 and $20 will yield the budget matched perfectly. However, a implementation that buys the most expensive item first will fail!
|
||||
|
||||
Similarly, a implementation that does the opposite will fail too: five items, [$50, $25, $15, $5, $1], budget of $65. The implementationn will attempt a combination of $1, $5, $15, and $25 for a total of $46. The proper choice would in fact be $50 and $15. The choices picked have no distinct pattern, and a `Combinations` algorithm will need to be implemented, which can be very difficult for those new to it (me included!).
|
||||
|
||||
My implementation is incomplete as of this moment.
|
||||
128
uil/aplus-february-2015/11/Spending.java
Normal file
128
uil/aplus-february-2015/11/Spending.java
Normal file
@@ -0,0 +1,128 @@
|
||||
import static java.lang.System.out;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Scanner;
|
||||
import java.util.Arrays;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
class Budget {
|
||||
private ArrayList<Item> list;
|
||||
private int budget;
|
||||
|
||||
Budget(ArrayList<Item> list, int budget) {
|
||||
this.list = (ArrayList<Item>) list.clone();
|
||||
this.budget = budget;
|
||||
}
|
||||
|
||||
// Output costliest affordable item
|
||||
private Item q1() {
|
||||
Item item = list.get(0);
|
||||
for (int i = 1; i < list.size(); i++) {
|
||||
if (list.get(i).price <= this.budget && list.get(i).price > item.price)
|
||||
item = list.get(i);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
// Count affordable prizes
|
||||
private int q2() {
|
||||
int i = 0;
|
||||
for (Item item : list)
|
||||
if (item.price <= budget)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Buy most prizes
|
||||
private int q3() {
|
||||
int n = 0;
|
||||
int curbudget = this.budget;
|
||||
for (Item item : list) {
|
||||
if (curbudget >= item.price) {
|
||||
curbudget -= item.price;
|
||||
n++;
|
||||
// out.println(String.format(">>> %s - %s (~$%s)", item.name, item.price, curbudget));
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public static ArrayList<Item[]> combinations(ArrayList<Item> list, int length) {
|
||||
ArrayList<Item[]> combos = new ArrayList<Item[]>();
|
||||
Item[] curcombo = new Item[length];
|
||||
Budget.combos(list, combos, curcombo, 0, length, 0, list.size() - 1);
|
||||
return combos;
|
||||
}
|
||||
|
||||
private static void combos(ArrayList<Item> originalList, ArrayList<Item[]> combosList, Item[] curcombo,
|
||||
int curIndex, int length, int start, int end) {
|
||||
if (curIndex == length) {
|
||||
combosList.add(curcombo);
|
||||
} else {
|
||||
for (int i = start; i <= end && end - i + 1 >= length - curIndex; i++) {
|
||||
curcombo[curIndex] = originalList.get(i);
|
||||
Budget.combos(originalList, combosList, curcombo, curIndex + 1, length, start + 1, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spend most money with best combo
|
||||
private int q4() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void evaluate() {
|
||||
Item a = q1();
|
||||
out.println(String.format("%s $%s", a.name, a.price));
|
||||
out.println(q2());
|
||||
out.println(q3());
|
||||
out.println(String.format("$%s", q4()));
|
||||
}
|
||||
}
|
||||
|
||||
class Item implements Comparable<Item> {
|
||||
String name;
|
||||
int price;
|
||||
|
||||
Item(String line) {
|
||||
int index = line.lastIndexOf(" ");
|
||||
this.name = line.substring(0, index);
|
||||
this.price = Integer.parseInt(line.substring(index + 1 + 1, line.length()));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("Item(%s, $%s)", this.name, this.price);
|
||||
}
|
||||
|
||||
public int compareTo(Item other) {
|
||||
return this.price - ((Item) other).price;
|
||||
}
|
||||
}
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
Scanner s = new Scanner(new File("spending.dat"));
|
||||
int lines = s.nextInt();
|
||||
s.nextLine();
|
||||
|
||||
// Aggregate all items
|
||||
ArrayList<Item> items = new ArrayList<Item>();
|
||||
for (int i = 0; i < lines; i++) {
|
||||
items.add(new Item(s.nextLine()));
|
||||
}
|
||||
|
||||
Collections.sort(items);
|
||||
Collections.reverse(items);
|
||||
|
||||
for (Item[] sub : Budget.combinations(items, 3))
|
||||
out.println(Arrays.toString(sub));
|
||||
|
||||
// Build all budgets, evaluate 4 questions
|
||||
ArrayList<Budget> budgets = new ArrayList<Budget>();
|
||||
while (s.hasNextInt()) {
|
||||
Budget budget = new Budget(items, s.nextInt());
|
||||
budget.evaluate();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
uil/aplus-february-2015/12/TicTacToe.MD
Normal file
20
uil/aplus-february-2015/12/TicTacToe.MD
Normal file
@@ -0,0 +1,20 @@
|
||||
# TicTacToe
|
||||
|
||||
Run my solution on **[repl.it](https://repl.it/@Xevion/A-Computer-Science-February-2015-TicTacToe)!**
|
||||
|
||||
A overall very fun problem, one of my absolute favorite in this set. Inputs were easy to understand, and I believe my implementation was short, sweet, and easy to understand (I feel clever, give me kudos)!
|
||||
|
||||
Understanding the flow of decision is important here, as otherwise you'll get weird outputs, even if your code evaluated 'as it should' (your implementation worked as it should, even if your implementation did not fit the problem's specifications).
|
||||
* First, you should check Verticals/Horizontals/Diagonals for a actual *solutions* (three identical marks in a row). If one is found, that's the answer.
|
||||
* Second, you should check that all places are filled in. If not, this is counted as a "Incomplete Board", and you should return in turn.
|
||||
* Third, if the above two don't match up, all spots are filled in, yet no one has won - it's a tie, return as such.
|
||||
|
||||
My implementation essentially came down to implementing methods that returned 3 item long arrays of rows, columns, and diagonal spaces. These were given a input of the common X or Y coordinate associated (diagonal used a 'rising' and 'falling' argument instead [True/False]).
|
||||
|
||||
Then, in the actual main method that 'solved' it, I iterated over the data, calling these methods and checking them against a 'equals' method, which simply checked that all 3 elements were equal to eachother using `String.equals`.
|
||||
|
||||
Implementation has already been explained above, so as a last word of advice when solving - make sure that your input data is correctly typed in! Since I manually did it based on what my paper said, I wasn't as careful as I could have been, and simply assumed that the data was correct (as it should be in real competition, as you receive a file, not type it yourself).
|
||||
|
||||
I failed to capitalize an `X` correctly and the `String.equals` method failed to pick up this. One could argue using `String.toUpperCase` would be a valid way of ensuring that the input data is case-insensitive.
|
||||
|
||||
Overall, an interesting problem that challenged me and my understanding of matrixes when implementing `vertical` and `horizontal` data aggregation methods.
|
||||
89
uil/aplus-february-2015/12/TicTacToe.java
Normal file
89
uil/aplus-february-2015/12/TicTacToe.java
Normal file
@@ -0,0 +1,89 @@
|
||||
import static java.lang.System.out;
|
||||
import java.util.Scanner;
|
||||
import java.util.Arrays;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
class Board {
|
||||
private String[][] board;
|
||||
|
||||
Board(String input) {
|
||||
this.board = new String[3][3];
|
||||
for(int i = 0; i < 9; i++)
|
||||
this.board[i / 3][i % 3] = input.substring(i, i + 1);
|
||||
}
|
||||
|
||||
// [[A, B, C], [D, E, F], [G, H, I]]
|
||||
// A B C | 0,0 1,0 2,0
|
||||
// D E F | 0,1 1,1 2,1
|
||||
// G H I | 0,2 1,2 2,2
|
||||
|
||||
public String[] vertical(int x) {
|
||||
return this.board[x];
|
||||
}
|
||||
public String[] horizontal(int y) {
|
||||
String[] vert = new String[3];
|
||||
for(int x = 0; x < 3; x++)
|
||||
vert[x] = this.board[x][y];
|
||||
return vert;
|
||||
}
|
||||
|
||||
public String[] diagonal(boolean rising) {
|
||||
String[] diag = new String[3];
|
||||
if(rising) {
|
||||
for(int i = 0; i < 3; i++)
|
||||
diag[i] = this.board[2 - i][2 - i];
|
||||
} else {
|
||||
for(int i = 0; i < 3; i++)
|
||||
diag[i] = this.board[i][i];
|
||||
}
|
||||
return diag;
|
||||
}
|
||||
|
||||
public boolean equal(String[] line) {
|
||||
return line[0].equals(line[1]) && line[1].equals(line[2]) && !line[0].equals("*");
|
||||
}
|
||||
|
||||
public String solve() {
|
||||
// Verticals
|
||||
for(int x = 0; x < 3; x++)
|
||||
if(this.equal(this.vertical(x)))
|
||||
return this.vertical(x)[0];
|
||||
// Horizontals
|
||||
for(int y = 0; y < 3; y++)
|
||||
if(this.equal(this.horizontal(y)))
|
||||
return this.horizontal(y)[0];
|
||||
// Diagonals
|
||||
if(this.equal(this.diagonal(false)))
|
||||
return this.diagonal(false)[0];
|
||||
if(this.equal(this.diagonal(true)))
|
||||
return this.diagonal(true)[0];
|
||||
|
||||
// Check for incompletion
|
||||
for(int x = 0; x < 3; x++) {
|
||||
for(int y = 0; y < 3; y++) {
|
||||
if(this.board[x][y].equals("*"))
|
||||
return "INC";
|
||||
}
|
||||
}
|
||||
|
||||
// Tie
|
||||
return "TIE";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("Board(%s)", Arrays.deepToString(this.board));
|
||||
}
|
||||
}
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
Scanner s = new Scanner(new File("tictactoe.dat"));
|
||||
s.nextLine();
|
||||
while(s.hasNextLine()) {
|
||||
String input = s.nextLine();
|
||||
Board board = new Board(input);
|
||||
out.println(board.solve());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user