Skip to content

Commit

Permalink
Fix Algorithm (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
henriqueleite42 committed Jul 18, 2022
1 parent 2fa285b commit 24a1049
Show file tree
Hide file tree
Showing 20 changed files with 501 additions and 263 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ One can perform the following operations on the jug:

The task is to determine whether it is possible to measure Z litres of water using both the jugs. And if true, print any of the possible ways.

**ALERT:** It still doesn't find the most efficient solution for all cases. If you want to fix this, please send a PR to this repo.

## Install

With Yarn:
Expand Down Expand Up @@ -71,19 +69,21 @@ console.log(
solvable: true,
minSteps: 4,
smallerJugCapacity: 2,
biggerJugCapacity: 10,
largerJugCapacity: 10,
steps: [
{
smallerJugContent: 2,
biggerJugContent: 0,
largerJugContent: 0,
index: "2,0",
action: {
type: "FILL",
bucket: "SMALLER",
jug: "SMALLER",
},
},
{
smallerJugContent: 0,
biggerJugContent: 2,
largerJugContent: 2,
index: "0,2",
action: {
type: "TRANSFER",
originJug: "SMALLER",
Expand All @@ -92,15 +92,17 @@ console.log(
},
{
smallerJugContent: 2,
biggerJugContent: 2,
largerJugContent: 2,
index: "2,2",
action: {
type: "FILL",
bucket: "SMALLER",
jug: "SMALLER",
},
},
{
smallerJugContent: 0,
biggerJugContent: 4,
largerJugContent: 4,
index: "0,4",
action: {
type: "TRANSFER",
originJug: "SMALLER",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@techmmunity/water-jug-solver",
"version": "1.0.0",
"version": "2.0.0",
"main": "index.js",
"types": "index.d.ts",
"license": "Apache-2.0",
Expand Down
2 changes: 1 addition & 1 deletion src/enums/jug.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export enum JugEnum {
SMALLER = "SMALLER",
BIGGER = "BIGGER",
LARGER = "LARGER",
}
11 changes: 0 additions & 11 deletions src/solution/helpers.ts

This file was deleted.

32 changes: 32 additions & 0 deletions src/solution/helpers/actions/empty-jug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */

import { getStepIndex } from "../get-step-index";

import type { ActionsState } from "./types";

import { JugEnum } from "../../../enums/jug";
import { StepActionEnum } from "../../../enums/step-action";
import type { SolutionStep } from "../../../types/solution";

export interface EmptyJugInput {
previousStep: SolutionStep;
target: JugEnum;
}

export type EmptyJugType = (p: EmptyJugInput) => SolutionStep;

export const makeEmptyJugAction =
(_state: ActionsState) =>
({ previousStep, target }: EmptyJugInput): SolutionStep => {
const { smallerJugContent, largerJugContent } = previousStep;

return {
smallerJugContent: target === JugEnum.SMALLER ? 0 : smallerJugContent,
largerJugContent: target === JugEnum.LARGER ? 0 : largerJugContent,
index: getStepIndex({ smallerJugContent, largerJugContent }),
action: {
type: StepActionEnum.EMPTY,
jug: target,
},
};
};
45 changes: 45 additions & 0 deletions src/solution/helpers/actions/fill-jug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */

import { getStepIndex } from "../get-step-index";

import type { ActionsState } from "./types";

import { JugEnum } from "../../../enums/jug";
import { StepActionEnum } from "../../../enums/step-action";
import type { SolutionStep } from "../../../types/solution";

export interface FillJugInput {
previousStep: SolutionStep;
target: JugEnum;
}

export type FillJugType = (p: FillJugInput) => SolutionStep;

export const makeFillJugAction =
({ smallerJugCapacity, largerJugCapacity }: ActionsState) =>
({ previousStep, target }: FillJugInput): SolutionStep => {
const { smallerJugContent, largerJugContent } = previousStep;

const jugCapacity =
target === JugEnum.SMALLER ? smallerJugCapacity : largerJugCapacity;

const newSmallerJugContent =
target === JugEnum.SMALLER ? jugCapacity : smallerJugContent;
const newLargerJugContent =
target === JugEnum.LARGER ? jugCapacity : largerJugContent;

const index = getStepIndex({
smallerJugContent: newSmallerJugContent,
largerJugContent: newLargerJugContent,
});

return {
smallerJugContent: newSmallerJugContent,
largerJugContent: newLargerJugContent,
index,
action: {
type: StepActionEnum.FILL,
jug: target,
},
};
};
16 changes: 16 additions & 0 deletions src/solution/helpers/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { makeEmptyJugAction } from "./empty-jug";
import { makeFillJugAction } from "./fill-jug";
import { makeTransferJugAction } from "./transfer-jug";
import type { ActionsState } from "./types";

export const makeActions = (actionsState: ActionsState) => {
const emptyJug = makeEmptyJugAction(actionsState);
const fillJug = makeFillJugAction(actionsState);
const transferJug = makeTransferJugAction(actionsState);

return {
emptyJug,
fillJug,
transferJug,
};
};
60 changes: 60 additions & 0 deletions src/solution/helpers/actions/transfer-jug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */

import { getStepIndex } from "../get-step-index";

import type { ActionsState } from "./types";

import { JugEnum } from "../../../enums/jug";
import { StepActionEnum } from "../../../enums/step-action";
import type { SolutionStep } from "../../../types/solution";

export interface TransferJugInput {
previousStep: SolutionStep;
target: JugEnum;
}

export type TransferJugType = (p: TransferJugInput) => SolutionStep;

export const makeTransferJugAction =
({ smallerJugCapacity, largerJugCapacity }: ActionsState) =>
({ previousStep, target }: TransferJugInput): SolutionStep => {
const { smallerJugContent, largerJugContent } = previousStep;

const targetJugCapacity =
target === JugEnum.SMALLER ? smallerJugCapacity : largerJugCapacity;

const originContent =
target === JugEnum.SMALLER ? smallerJugContent : largerJugContent;
const destinationContent =
target === JugEnum.SMALLER ? largerJugContent : smallerJugContent;

const toAvailability = targetJugCapacity - originContent;

const newDestinationContent = Math.min(
originContent + destinationContent,
targetJugCapacity,
);

const newOriginContent = Math.max(originContent - toAvailability, 0);

const newSmallerJugContent =
target === JugEnum.SMALLER ? newOriginContent : newDestinationContent;
const newLargerJugContent =
target === JugEnum.SMALLER ? newDestinationContent : newOriginContent;

const index = getStepIndex({
smallerJugContent: newSmallerJugContent,
largerJugContent: newLargerJugContent,
});

return {
smallerJugContent: newSmallerJugContent,
largerJugContent: newLargerJugContent,
index,
action: {
type: StepActionEnum.TRANSFER,
originJug: target === JugEnum.SMALLER ? JugEnum.LARGER : target,
destinationJug: target === JugEnum.SMALLER ? target : JugEnum.LARGER,
},
};
};
4 changes: 4 additions & 0 deletions src/solution/helpers/actions/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface ActionsState {
smallerJugCapacity: number;
largerJugCapacity: number;
}
55 changes: 55 additions & 0 deletions src/solution/helpers/add-step-to-possible-solutions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */
import type { SolutionStep } from "../../types/solution";

interface AddStepToPossibleSolutions {
previousStep: SolutionStep;
step: SolutionStep;
possibleSolutions: Array<Array<SolutionStep>>;
}

export const addStepToPossibleSolutions = ({
previousStep,
step,
possibleSolutions,
}: AddStepToPossibleSolutions) => {
const possibleSolutionsClone = JSON.parse(
JSON.stringify(possibleSolutions),
) as Array<Array<SolutionStep>>;

const found = possibleSolutionsClone.find(states => {
const lastIndex = states.at(-1)!;

return lastIndex.index === previousStep.index;
});

if (found) {
found.push(step);

return {
possibleSolutions: possibleSolutionsClone,
solutionDeep: found.length,
};
}

const foundSecondFromLast = possibleSolutionsClone.find(states => {
const secondFromLast = states.at(-2)!;

return secondFromLast.index === previousStep.index;
});

if (foundSecondFromLast) {
possibleSolutionsClone.push([...foundSecondFromLast.slice(0, -1), step]);

return {
possibleSolutions: possibleSolutionsClone,
solutionDeep: foundSecondFromLast.length,
};
}

possibleSolutionsClone.push([previousStep, step]);

return {
possibleSolutions: possibleSolutionsClone,
solutionDeep: 2,
};
};
18 changes: 18 additions & 0 deletions src/solution/helpers/get-jugs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface GetJugsInput {
firstJugCapacity: number;
secondJugCapacity: number;
}

export const getJugs = ({
firstJugCapacity,
secondJugCapacity,
}: GetJugsInput) => {
const [smaller, larger] = [firstJugCapacity, secondJugCapacity].sort(
(a, b) => a - b,
);

return {
smallerJugCapacity: smaller,
largerJugCapacity: larger,
};
};
46 changes: 46 additions & 0 deletions src/solution/helpers/get-states.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { EmptyJugType } from "./actions/empty-jug";
import type { FillJugType } from "./actions/fill-jug";
import type { TransferJugType } from "./actions/transfer-jug";

import { JugEnum } from "../../enums/jug";
import type { SolutionStep } from "../../types/solution";

export interface GetStates {
actions: {
emptyJug: EmptyJugType;
fillJug: FillJugType;
transferJug: TransferJugType;
};
previousStep: SolutionStep;
}

export const getStates = ({ actions, previousStep }: GetStates) => {
const { emptyJug, fillJug, transferJug } = actions;

return [
fillJug({
previousStep,
target: JugEnum.SMALLER,
}),
fillJug({
previousStep,
target: JugEnum.LARGER,
}),
emptyJug({
previousStep,
target: JugEnum.SMALLER,
}),
emptyJug({
previousStep,
target: JugEnum.LARGER,
}),
transferJug({
previousStep,
target: JugEnum.SMALLER,
}),
transferJug({
previousStep,
target: JugEnum.LARGER,
}),
];
};
7 changes: 7 additions & 0 deletions src/solution/helpers/get-step-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { SolutionStep } from "../../types/solution";

export const getStepIndex = ({
smallerJugContent,
largerJugContent,
}: Pick<SolutionStep, "largerJugContent" | "smallerJugContent">) =>
`${smallerJugContent},${largerJugContent}`;
5 changes: 5 additions & 0 deletions src/solution/helpers/is-even-odd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */

export const isEven = (nbr: number) => nbr % 2 === 0;

export const isOdd = (nbr: number) => !isEven(nbr);
13 changes: 13 additions & 0 deletions src/solution/helpers/state-has-goal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface StepHasGoal {
smallerJugContent: number;
largerJugContent: number;
desiredAmount: number;
}

export const stepHasGoal = ({
smallerJugContent,
largerJugContent,
desiredAmount,
}: StepHasGoal): boolean =>
[smallerJugContent, largerJugContent].includes(desiredAmount) ||
smallerJugContent + largerJugContent === desiredAmount;

0 comments on commit 24a1049

Please sign in to comment.