Skip to content

Commit

Permalink
feat: day 24 part 2 WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Flashky committed Dec 24, 2024
1 parent 7b586a8 commit d5e720b
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 0 deletions.
154 changes: 154 additions & 0 deletions src/main/java/com/adventofcode/flashk/day24/CrossedWires.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package com.adventofcode.flashk.day24;

import org.apache.commons.lang3.StringUtils;
import org.jgrapht.graph.DirectedMultigraph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class CrossedWires {

private static final Pattern GATE_PATTERN = Pattern.compile("(\\w*) (AND|XOR|OR) (\\w*) -> (\\w*)");

private DirectedMultigraph<LogicalGate,WireEdge> graph = new DirectedMultigraph<>(WireEdge.class);

Map<String, Wire> wires = new HashMap<>();
private final List<LogicalGate> gates = new ArrayList<>();

// Attributes that help start and end the algorithm
private final List<LogicalGate> initialGates = new ArrayList<>();
private final List<Wire> endWires = new ArrayList<>();

public CrossedWires(List<String> inputs) {

// Maps a wire with the gate that generates it.
Map<Wire,LogicalGate> originGates = new HashMap<>();

boolean inputWires = true;

for (String input : inputs) {
if (StringUtils.isBlank(input)) {
inputWires = false;
continue;
}

if (inputWires) {
String[] wireInput = input.replace(StringUtils.SPACE, StringUtils.EMPTY).split(":");
wires.put(wireInput[0], new Wire(wireInput[0], Integer.parseInt(wireInput[1])));
} else {
createGate(input, originGates);
}
}


// Connect graph gates
/*
for(LogicalGate gate : gates) {
// First input
if(originGates.containsKey(gate.getInput1())) {
Gate inputGate1 = originGates.get(gate.getInput1());
graph.addEdge(inputGate1, gate, new WireEdge(gate.getInput1()));
}
// Second input
if(originGates.containsKey(gate.getInput2())) {
Gate inputGate2 = originGates.get(gate.getInput2());
graph.addEdge(inputGate2, gate, new WireEdge(gate.getInput2()));
}
}
*/
}

private void createGate(String input, Map<Wire,LogicalGate> wireOriginGates) {
Matcher matcher = GATE_PATTERN.matcher(input);
if(matcher.find()) {

// Create the gate vertex
String operation = matcher.group(2);
LogicalGate gate = new LogicalGate(operation);

// Create the wires
getOrCreateWire(matcher.group(1)); // Input wire 1
getOrCreateWire(matcher.group(3)); // Input wire 2
Wire outputWire = getOrCreateWire(matcher.group(4));


// Add it to structures
gates.add(gate);
graph.addVertex(gate);

/*
if(gate.canOperate()) {
initialGates.add(gate);
}*/

// Wire management for building the graph
if(outputWire.getLabel().startsWith("z")) {
endWires.add(outputWire);
}

wireOriginGates.put(outputWire, gate);

}
}

private void buildGraph() {
LogicalGate start = new StartGate("OR");

}
/// Retrieves a [Wire]() associated to the label.
///
/// If the label does not exist, it creates a new wire and returns it.
/// @param label the wire label
/// @return a [Wire]()
private Wire getOrCreateWire(String label) {
Wire wire = wires.getOrDefault(label, new Wire(label));
wires.putIfAbsent(label, wire);
return wire;
}

public long solveA() {

/*
PriorityQueue<Gate> gates = new PriorityQueue<>();
gates.addAll(initialGates);
while(!gates.isEmpty()) {
// Extract first those gates which can operate
Gate gate = gates.poll();
gate.setVisited(true);
// Operate it
WireEdge outputEdge = gate.operate();
Wire output = outputEdge.wire();
System.out.println("Wire "+output.getLabel()+ " has value: "+output.getValue().get());
// Calculate the next gate that should be added to the queue.
if(!output.isEnd()) {
Gate outputGate = graph.getEdgeTarget(outputEdge);
if(!outputGate.isVisited()) {
gates.add(outputGate);
}
}
}*/

String binaryValue = endWires.stream().sorted().map(Wire::getBinaryValue).collect(Collectors.joining());
return Long.valueOf(binaryValue, 2);
}

private Set<Gate> getAdjacents(Gate gate) {
// TODO cálculo de adyacentes
return new HashSet<>();
}
}
69 changes: 69 additions & 0 deletions src/main/java/com/adventofcode/flashk/day24/Gate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.adventofcode.flashk.day24;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;

import java.util.UUID;

@Getter
@Setter
@EqualsAndHashCode
public class Gate implements Comparable<Gate> {

private String id = UUID.randomUUID().toString();
private String operation;
private Wire input1;
private Wire input2;
private Wire output;
private WireEdge outputEdge;

private boolean visited = false;

public Gate(String operation, Wire input1, Wire input2, Wire output) {
this.operation = operation;
this.input1 = input1;
this.input2 = input2;
this.output = output;
this.outputEdge = new WireEdge(output);
}

public boolean canOperate() {
return input1.hasCurrent() && input2.hasCurrent();
}

/// Operates the gate using its inputs wires
///
/// @return the output [Wire]()
/// @throws IllegalStateException if any of the wires has no value present or if the gate operation is unknown.
public WireEdge operate() {

int value1 = input1.getValue().orElseThrow(IllegalStateException::new);
int value2 = input2.getValue().orElseThrow(IllegalStateException::new);

switch (operation) {
case "AND" -> output.setValue(value1 & value2);
case "XOR" -> output.setValue(value1 ^ value2);
case "OR" -> output.setValue(value1 | value2);
case null, default -> throw new IllegalStateException("Unknown gate operation: " + operation);
}

return outputEdge;
}


@Override
public int compareTo(@NotNull Gate o) {
if(this.canOperate() && !o.canOperate()) {
return -1;
}

if(!this.canOperate() && o.canOperate()) {
return 1;
}

return 0;
}

}
40 changes: 40 additions & 0 deletions src/main/java/com/adventofcode/flashk/day24/LogicalGate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.adventofcode.flashk.day24;

import java.util.UUID;

public class LogicalGate {

private final String id = UUID.randomUUID().toString();
private final String operation;

public LogicalGate(String operation) {
this.operation = operation;
}

public boolean canOperate(Wire input1, Wire input2) {
return input1.getValue().isPresent() && input2.getValue().isPresent();
}

/// Operates the gate using its inputs wires
///
/// @return the output [Wire]()
/// @throws IllegalStateException if any of the wires has no value present or if the gate operation is unknown.
public int operate(Wire input1, Wire input2) {

int value1 = input1.getValue().orElseThrow(IllegalStateException::new);
int value2 = input2.getValue().orElseThrow(IllegalStateException::new);

int result;

switch (operation) {
case "AND" -> result = value1 & value2;
case "XOR" -> result = value1 ^ value2;
case "OR" -> result = value1 | value2;
case null, default -> throw new IllegalStateException("Unknown gate operation: " + operation);
}

return result;

}

}
10 changes: 10 additions & 0 deletions src/main/java/com/adventofcode/flashk/day24/StartGate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.adventofcode.flashk.day24;

public class StartGate extends LogicalGate {

public StartGate(String operation) {
super(operation);
}


}
59 changes: 59 additions & 0 deletions src/main/java/com/adventofcode/flashk/day24/Wire.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.adventofcode.flashk.day24;


import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;

import java.util.Optional;

@Getter
@EqualsAndHashCode
public class Wire implements Comparable<Wire>{

private final String label;

@Setter
private int value;

public Wire(String label, int value) {
this.label = label;
this.value = value;
}

public Wire(String label) {
this.label = label;
this.value = -1;
}

public String getBinaryValue() {
if(value == -1) {
throw new IllegalStateException("Cannot convert to binary a non set value");
}
return String.valueOf(value);
}

public Optional<Integer> getValue() {
if(value == -1) {
return Optional.empty();
}
return Optional.of(value);
}

public boolean hasCurrent() {
return value != -1;
}

public boolean isStart() {
return label.startsWith("x") || label.startsWith("y");
}
public boolean isEnd() {
return label.startsWith("z");
}

@Override
public int compareTo(@NotNull Wire o) {
return -1 * this.label.compareTo(o.label);
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/adventofcode/flashk/day24/WireEdge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.adventofcode.flashk.day24;

import java.util.UUID;

public record WireEdge(String id, Wire wire) {

public WireEdge(Wire wire) {
this(UUID.randomUUID().toString(), wire);
}
}

0 comments on commit d5e720b

Please sign in to comment.