Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mon foobarqix étendu #2

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
40 changes: 40 additions & 0 deletions foobarqix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Principes de mise en oeuvre
===========================

Ce programme affiche les nombres de 1 à 100. Un nombre par ligne, respectant les règles du FooBarQix.
Il permet également l'évaluation FooBarQix d'entiers de taille indéfinie.
L'algorithme peut être modifié/enrichi simplement.

* L'algorithme de translation

L'algorithme translation permet de retourner une chaine résultat en fonction d'un texte passé en entrée.
Le comportement de l'algorithme doit être défini au travers de règles. Il existe actuellement deux règles: une régle sur la divisibilité et une de comparaison de contenu.

Remarque: Cet algorithme est paramétré spécifiquement pour le FooBarQix dans la classe du même nom.

* Critère de divisibilité

Pour déterminer si un nombre est divisible, on utilise 2 algorithmes différents:
si le nombre peut être casté en int, on utilise un simple modulo.
si le nombre est trop grand, on utilise les critères de divibilité.
Voir http://fr.wikipedia.org/wiki/Liste_de_crit%C3%A8res_de_divisibilit%C3%A9#Entiers_inf.C3.A9rieurs_.C3.A0_10.
Actuellement, seuls les critères de divisibilité pour les 3, 5 et 7 sont implémentés.


Buid & Tests
============

* mvn package

Execution
=========

* mvn exec:java


Utilisation
===========

* Pour quitter le programme, taper la lettre q.
* Pour obtenir les 100 premiers résultat tel que demandé par l'exercie, taper le mot list à la demande de saisie.
* Toute autre entrée sera interprêtée comme une valeur à évaluer par le FooBarQix.
38 changes: 38 additions & 0 deletions foobarqix/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sebdev</groupId>
<artifactId>foobarqix</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>foobarqix</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<mainClass>com.sebdev.foobarqix.Runner</mainClass>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
56 changes: 56 additions & 0 deletions foobarqix/src/main/java/com/sebdev/foobarqix/FooBarQix.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.sebdev.foobarqix;

import com.sebdev.translation.TranslationEngine;
import com.sebdev.math.VeryBigInteger;
import com.sebdev.translation.rule.Rule;
import com.sebdev.translation.rule.RuleComparedContent;
import com.sebdev.translation.rule.RuleDivisible;
import java.util.ArrayList;
import java.util.List;

/**
* FooBarQix algorithm
*/
public class FooBarQix {

//FooBarQix constants
private static final int FOO_NUMBER = 3;
private static final String FOO_TEXT = "Foo";
private static final int BAR_NUMBER = 5;
private static final String BAR_TEXT = "Bar";
private static final int QIX_NUMBER = 7;
private static final String QIX_TEXT = "Qix";
private final TranslationEngine engine;

public FooBarQix() {
List<Rule> rules = initTranslationForFooBarQix();
engine = new TranslationEngine(rules);
}

private boolean hasToBeReturnedAsIt(String userInput) {
return !VeryBigInteger.isInteger(userInput);
}

/**
* Instanciate Translation Algorithm with FooBarQix rules
*/
private List<Rule> initTranslationForFooBarQix() {
List<Rule> rules = new ArrayList<Rule>();
rules.add(new RuleDivisible(FOO_NUMBER, FOO_TEXT));
rules.add(new RuleDivisible(BAR_NUMBER, BAR_TEXT));
rules.add(new RuleDivisible(QIX_NUMBER, QIX_TEXT));
rules.add(new RuleComparedContent(new int[]{FOO_NUMBER, BAR_NUMBER, QIX_NUMBER},
new String[]{FOO_TEXT, BAR_TEXT, QIX_TEXT}));
return rules;
}

/**
* Execute the FooBarQix on the user inupt
*/
protected String compute(String userInput) {
if (hasToBeReturnedAsIt(userInput)) {
return userInput;
}
return engine.compute(userInput);
}
}
50 changes: 50 additions & 0 deletions foobarqix/src/main/java/com/sebdev/foobarqix/Runner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.sebdev.foobarqix;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
* Main du programme FooBarQix
*/
public class Runner {

private static final String EXIT_CHAR = "q";
private static final String WRITE_0_100 = "list";

/**
* Usage:
* enter q to exit program
* enter list to writer foobarqix for numbers 1 to 100
* enter any value to display the foobarqix result
*/
public static void main(String[] args) throws Exception {
Runner runner = new Runner();
runner.execute();
}

protected void execute() throws IOException {
FooBarQix foobarQix = new FooBarQix();
String userInput = null;
while (!EXIT_CHAR.equals(userInput)) {
System.out.print("Veuillez saisir une valeur (list pour 0-100; q pour sortir):");
userInput = inputString();
if (hasToBeComputedForNumbers1To100(userInput)) {
for (int number = 1; number <= 100; number++) {
System.out.println(foobarQix.compute(Integer.toString(number)));
}
} else {
System.out.println(foobarQix.compute(userInput));
}
}
}

protected String inputString() throws IOException {
BufferedReader inr = new BufferedReader(new InputStreamReader(System.in));
return (inr.readLine());
}

private boolean hasToBeComputedForNumbers1To100(String userInput) {
return WRITE_0_100.equals(userInput);
}
}
12 changes: 12 additions & 0 deletions foobarqix/src/main/java/com/sebdev/math/MathUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sebdev.math;

public class MathUtils {

/**
* Return true if numerator is divible by divisor
* @return
*/
public static boolean isDivisibleBy(int numerator, int divisor) {
return (numerator % divisor) == 0;
}
}
65 changes: 65 additions & 0 deletions foobarqix/src/main/java/com/sebdev/math/VeryBigInteger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.sebdev.math;

import com.sebdev.math.divisiblecriteria.UnknowCriteriaRule;
import com.sebdev.math.divisiblecriteria.AbstractDivisibleCriteria;
import com.sebdev.math.divisiblecriteria.DivisbleCriteriaFive;
import com.sebdev.math.divisiblecriteria.DivisibleCriteriaSeven;
import com.sebdev.math.divisiblecriteria.DivisibleCriteriaThree;
import java.util.HashMap;
import java.util.Map;

/**
* Specific Methods for what we call a very big integer in this project
*/
public class VeryBigInteger {

private static final Map<Integer, AbstractDivisibleCriteria> divisibleCriteria;

static {
divisibleCriteria = new HashMap<Integer, AbstractDivisibleCriteria>();
DivisibleCriteriaThree dc3 = new DivisibleCriteriaThree();
divisibleCriteria.put(dc3.getDivisorValue(), dc3);
DivisbleCriteriaFive dc5 = new DivisbleCriteriaFive();
divisibleCriteria.put(dc5.getDivisorValue(), dc5);
DivisibleCriteriaSeven dc7 = new DivisibleCriteriaSeven();
divisibleCriteria.put(dc7.getDivisorValue(), dc7);
}
private final String value;

public VeryBigInteger(String value) {
this.value = value;
}

/**
* Return true if the veryBigInterger is divisible by divisor
*/
public boolean isDivisibleBy(int divisor) {
try {
int intValue = Integer.valueOf(this.value);
return MathUtils.isDivisibleBy(intValue, divisor);
} catch (NumberFormatException ex) {
//For a too big integer, we need to use defined criteria
if (!divisibleCriteria.containsKey(divisor)) {
throw new UnknowCriteriaRule(divisor);
}
return divisibleCriteria.get(divisor).isDivisible(this.value);
}
}

/**
* return true if the parameter is an integer
*/
public static boolean isInteger(String value) {
for (char car : value.toCharArray()) {
if (!Character.isDigit(car)) {
return false;
}
}
return true;
}

@Override
public String toString() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.sebdev.math.divisiblecriteria;

public abstract class AbstractDivisibleCriteria {

public abstract boolean isDivisible(String value);

/**
* This method parse an integer reprensented by a string in piece of n digits
* @param veryBigInteger - integer to parse
* @param parsingSize - number of digit of each piece
* @return - int array of veryBigInteger parsing result
*/
protected int[] parseStringToIntArray(String veryBigInteger, int parsingSize) {
int firstPieceSize = veryBigInteger.length() % parsingSize;
int numberOfPieces = calculateSizeOfGeneratedArray(veryBigInteger.length(), parsingSize, firstPieceSize);
int[] result = new int[numberOfPieces];
int beginIndex = 0;
int endIndex = (firstPieceSize == 0 ? parsingSize : firstPieceSize);
for (int resultIndex = 0; resultIndex < result.length; resultIndex++) {
result[resultIndex] = Integer.parseInt(veryBigInteger.substring(beginIndex, endIndex));
beginIndex = endIndex;
endIndex = endIndex + parsingSize;
}

return result;
}

private int calculateSizeOfGeneratedArray(int veryBigIntegerLength, int parseLenght, int firstPieceSize) {
int numberOfPieces = veryBigIntegerLength / parseLenght;
if (firstPieceSize != 0) {
numberOfPieces++;
}
return numberOfPieces;
}

/**
* @return the value for which the criteria is created
*/
public abstract int getDivisorValue();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.sebdev.math.divisiblecriteria;

/**
* Implementation of criteria rule specific to divisor 5
*/
public class DivisbleCriteriaFive extends AbstractDivisibleCriteria {

@Override
public boolean isDivisible(String value) {
int[] parsedVeryBigInteger = parseStringToIntArray(value, 1);
int lastDigit = parsedVeryBigInteger[parsedVeryBigInteger.length - 1];
return (lastDigit == 0 || lastDigit == 5);
}

@Override
public int getDivisorValue() {
return 5;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.sebdev.math.divisiblecriteria;

import com.sebdev.math.MathUtils;

/**
* Implementation of criteria rule specific to divisor 7
*/
public class DivisibleCriteriaSeven extends AbstractDivisibleCriteria {

@Override
public boolean isDivisible(String value) {

int[] parsedVeryBigInteger = parseStringToIntArray(value, 3);
int valueToEvaluate = 0;
for (int index = 0; index < parsedVeryBigInteger.length; index++) {
if (index % 2 == 0) {
valueToEvaluate += parsedVeryBigInteger[index];
} else {
valueToEvaluate -= parsedVeryBigInteger[index];
}
}

return MathUtils.isDivisibleBy(valueToEvaluate, 7);
}

@Override
public int getDivisorValue() {
return 7;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sebdev.math.divisiblecriteria;

import com.sebdev.math.MathUtils;

/**
* Implementation of criteria rule specific to divisor 3
*/
public class DivisibleCriteriaThree extends AbstractDivisibleCriteria {

@Override
public boolean isDivisible(String value) {
int[] parsedVeryBigInteger = parseStringToIntArray(value, 1);
int total = 0;
for (int digit : parsedVeryBigInteger) {
total += digit;
}
return MathUtils.isDivisibleBy(total, 3);
}

@Override
public int getDivisorValue() {
return 3;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.sebdev.math.divisiblecriteria;

public class UnknowCriteriaRule extends RuntimeException {

public UnknowCriteriaRule(int divisor) {
super("Criteria rule unkwown for divisor " + divisor);
}
}
Loading