General FizzBuzz/jFizzBuzz: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Added more detailed error message.)
No edit summary
 
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
<syntaxhighlight lang="java">

/**
{{works with|Java|1.8.x}}
* @file GeneralFizzBuzz.java

User-supplied values must be passed as command-line arguments.

<lang Java>/**
*
* FizzBuzz Enterprise Edition (c) 2016
*
*
* TODO: Add End-User License Agreement
* TODO: Add JavaDoc Comments
* TODO: Add Unit Tests
* TODO: Add Dependency Injection (FizzBuzzProvider, BuzzerProvider, etc.)
*
*
*/
*/


import java.io.InputStream;
package com.fizzbuzzinc.jfizzbuzz;
import java.io.OutputStream;

import java.io.PrintWriter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Scanner;




/**
class BuzzException extends Exception
* This class follows the "God class" pattern.
* See {@link #main(String[])} for example usage.
*/
class FizzBuzzer
implements
Iterable<FizzBuzzer.Entry>,
Iterator<FizzBuzzer.Entry>
{
{
private static final long DEFAULT_START_NUM = 1;
public BuzzException(
private static final long DEFAULT_MAX_NUM = Long.MAX_VALUE;
String textualRepresentation
)
{
super(textualRepresentation);
}
}


public class Entry {


public final long num;
interface IBuzzer
public final List<String> names;
{
void buzz(
Integer numericValue
)
throws BuzzException;
}


private Entry(Long num, List<String> names) {
this.num = num;
this.names = names;
}
}


private Map<Integer, String> modToName = new HashMap<>();
interface IFizzBuzz
{
Boolean addBuzzer(
IBuzzer buzzerToAddToTheListOfBuzzers
);


private long currNum = DEFAULT_START_NUM;
String doExecute();
private long maxNum = DEFAULT_MAX_NUM;
}
private Map<Long, List<Integer>> schedule = new HashMap<>();


public long getCurrNum() { return currNum; }
public void setCurrNum(long currNum) { this.currNum = currNum; }

public long getMaxNum() { return maxNum; }
public void setMaxNum(long maxNum) { this.maxNum = maxNum; }


class Buzzer implements IBuzzer
{
protected final Integer numericValue;
protected final String textualRepresentation;


private List<Integer> scheduledAt(long num) {
public Buzzer(
return schedule.computeIfAbsent(num, num_ -> new ArrayList<>());
Integer numericValue,
String textualRepresentation
)
{
this.numericValue = numericValue;
this.textualRepresentation = textualRepresentation;
}
}


public void buzz(
private void scheduleNearest(Integer mod) {
Integer numericValue
)
throws BuzzException
{
Integer moduloOfNumericValues = new Integer(numericValue % this.getNumericValue());


long nearestNum = currNum + (mod - currNum % mod);
if (moduloOfNumericValues.equals(new Integer(0)))
{
throw new BuzzException(this.getTextualRepresentation());
}


scheduledAt(nearestNum).add(mod);
}
}


public boolean add(Integer mod, String name) {
Integer getNumericValue()
{
return this.numericValue;
}


if (modToName.containsKey(mod)) {
String getTextualRepresentation()
return false;
{
}
return this.textualRepresentation;
}
}


modToName.put(mod, name);
scheduleNearest(mod);


return true;
/**
*
* Thread-safe implementation of {@link IFizzBuzz}.
*
*/
class FizzBuzz implements IFizzBuzz
{
protected final Integer numericvalueOfUpperLimit;
protected final List<IBuzzer> listOfBuzzers;

public FizzBuzz(
Integer numericvalueOfUpperLimit
)
{
this.numericvalueOfUpperLimit = numericvalueOfUpperLimit;
this.listOfBuzzers = new ArrayList<IBuzzer>();
}
}


public void addAll(Map<Integer, String> modToName) {
public synchronized Boolean addBuzzer(

IBuzzer buzzerToAddToTheListOfBuzzers
for (Map.Entry<Integer, String> modAndName : modToName.entrySet()) {
)
add(modAndName.getKey(), modAndName.getValue());
{
}
return new Boolean(this.listOfBuzzers.add(buzzerToAddToTheListOfBuzzers));
}
}


public synchronized String doExecute()
{
StringBuilder textualRepresentationOfFizzBuzzProgramOutput = new StringBuilder();


for (
@Override
public Entry next() {
Integer loopIndex = new Integer(1);
loopIndex <= this.numericvalueOfUpperLimit;
loopIndex += new Integer(1)
)
{
Boolean atLeastOneBuzzerBuzzed = new Boolean(false);


for (
List<Integer> currMods = scheduledAt(currNum);
Integer buzzerIndex = new Integer(0);
buzzerIndex < new Integer(this.listOfBuzzers.size());
buzzerIndex += new Integer(1)
)
{
IBuzzer buzzer = this.listOfBuzzers.get(buzzerIndex);
try
{
buzzer.buzz(loopIndex);
}
catch (BuzzException buzzException)
{
textualRepresentationOfFizzBuzzProgramOutput.append(buzzException.getMessage());
atLeastOneBuzzerBuzzed = new Boolean(true);
}
}


List<String> currNames = new ArrayList<>();
if (atLeastOneBuzzerBuzzed.equals(new Boolean(false)))
{
textualRepresentationOfFizzBuzzProgramOutput.append(loopIndex.toString());
}


for (Integer m : currMods) {
textualRepresentationOfFizzBuzzProgramOutput.append(new String("\n"));
}


String name = modToName.get(m);
return textualRepresentationOfFizzBuzzProgramOutput.toString();
currNames.add(name);


long newNum = currNum + m;
}
scheduledAt(newNum).add(m);

}


class FizzBuzzEnterpriseDemo
{
public static void main(
String[] programArgumentsAsProvidedByTheEndUser
)
{
final UserSuppliedArguments userSuppliedArguments;

try
{
userSuppliedArguments = new UserSuppliedArguments(programArgumentsAsProvidedByTheEndUser);
}
catch (IllegalArgumentException illegalArgumentException)
{
System.err.println(illegalArgumentException.getMessage());
System.exit(1);
return;
}
}


Entry result = new Entry(currNum, currNames);
final FizzBuzz fizzBuzz = new FizzBuzz(userSuppliedArguments.numericValueOfUpperLimit);


currNum++;
Iterator buzzerEntriesIterator = userSuppliedArguments.buzzerEntries.entrySet().iterator();


return result;
while (buzzerEntriesIterator.hasNext())
{
}
Map.Entry numericValueTextualRepresentationPair = (Map.Entry) buzzerEntriesIterator.next();


@Override
fizzBuzz.addBuzzer(new Buzzer(
public void remove() {
(Integer) numericValueTextualRepresentationPair.getKey(),
schedule.remove(currNum - 1);
(String) numericValueTextualRepresentationPair.getValue()
));
}
}


@Override
System.out.println(fizzBuzz.doExecute());
public boolean hasNext() {
return (maxNum < 0) || (currNum <= maxNum);
}


@Override
public Iterator<Entry> iterator() {
return this;
}
}




private static class UserSuppliedArguments
public static FizzBuzzer readFrom(InputStream in) {
{
public final Integer numericValueOfUpperLimit;
public final Map<Integer,String> buzzerEntries;


private UserSuppliedArguments(
FizzBuzzer fizzBuzzer = new FizzBuzzer();
String[] sourceArguments
)
throws IllegalArgumentException
{
Integer requiredAmountOfUserSuppliedArguments = new Integer(7);
Integer actualAmountOfUserSuppliedArguments = new Integer(sourceArguments.length);


try (Scanner scanner = new Scanner(in)) {
if (actualAmountOfUserSuppliedArguments < requiredAmountOfUserSuppliedArguments)
{
throw new IllegalArgumentException(String.format(
"End user did not provide sufficient amount of command-line program arguments.\n"+
"Required amount of arguments: %d\n"+
"Amount of arguments supplied by the end used: %d\n",
requiredAmountOfUserSuppliedArguments, actualAmountOfUserSuppliedArguments
));
}


this.buzzerEntries = new LinkedHashMap<Integer,String>();
long maxNum = scanner.nextLong();
fizzBuzzer.setMaxNum(maxNum);


while (scanner.hasNext()) {


String textualValueOfUpperLimit = sourceArguments[new Integer(0)];
Integer mod = scanner.nextInt();
Integer numericValueOfUpperLimit;
scanner.skip("[\t ]*");
String name = scanner.nextLine();


try
fizzBuzzer.add(mod, name);
{
numericValueOfUpperLimit = new Integer(textualValueOfUpperLimit);
if (numericValueOfUpperLimit < new Integer(0))
{
throw new IllegalArgumentException();
}
}
catch (IllegalArgumentException illegalArgumentException)
{
throw new IllegalArgumentException(String.format(
"End user supplied invalid value for upper limit for the FizzBuzz execution.\n"+
"Required non-negative integer value.\n"+
"Value supplied by the end user: %s\n",
textualValueOfUpperLimit
));
}
}
}


return fizzBuzzer;
this.numericValueOfUpperLimit = numericValueOfUpperLimit;
}


public void printTo(OutputStream out) {


for (
try (PrintWriter writer = new PrintWriter(out)) {
Integer loopIndex = new Integer(1);
loopIndex <= new Integer(3);
loopIndex += new Integer(1)
)
{
Integer numericValueArgumentIndex = loopIndex * new Integer(2) - new Integer(1);
Integer textualRepresentationArgumentIndex = numericValueArgumentIndex + new Integer(1);


Integer buzzerNumericValue;
for (FizzBuzzer.Entry e : this) {
String buzzerTextualValue;
String buzzerTextualRepresentation;


String strNames = String.join(" ", e.names);
buzzerTextualRepresentation = sourceArguments[textualRepresentationArgumentIndex];
String line = String.format("%d %s", e.num, strNames);
buzzerTextualValue = sourceArguments[numericValueArgumentIndex];


try
writer.println(line);
{
writer.flush();
buzzerNumericValue = new Integer(buzzerTextualValue);
if (buzzerNumericValue <= new Integer(0))
{
throw new IllegalArgumentException();
}
}
catch (IllegalArgumentException illegalArgumentException)
{
throw new IllegalArgumentException(String.format(
"End user supplied invalid numeric value for buzzer %d.\n"+
"Required positive integer value.\n"+
"Value supplied by the end user: %s\n",
loopIndex, buzzerTextualValue
));
}


this.buzzerEntries.put(buzzerNumericValue, buzzerTextualRepresentation);
remove();
}
}

}
}
}


@Override
public String toString() {
return String.format("%s; current %d; max %d",
modToName, currNum, maxNum);
}
}

}
}


class GeneralFizzBuzz {
</lang>

public static void main(String[] args) {

try {
FizzBuzzer.readFrom(System.in).printTo(System.out);
}

catch (NoSuchElementException | IllegalStateException e) {

System.err.format("Error: %s\n", e.toString());
System.exit(1);
}
}
}</syntaxhighlight>

Latest revision as of 09:50, 15 June 2023

/**
 * @file GeneralFizzBuzz.java
 */

import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Scanner;


/**
 * This class follows the "God class" pattern.
 * See {@link #main(String[])} for example usage.
 */
class FizzBuzzer
implements
    Iterable<FizzBuzzer.Entry>,
    Iterator<FizzBuzzer.Entry>
{
    private static final long DEFAULT_START_NUM = 1;
    private static final long DEFAULT_MAX_NUM = Long.MAX_VALUE;

    public class Entry {

        public final long num;
        public final List<String> names;

        private Entry(Long num, List<String> names) {
            this.num = num;
            this.names = names;
        }
    }

    private Map<Integer, String> modToName = new HashMap<>();

    private long currNum = DEFAULT_START_NUM;
    private long maxNum  = DEFAULT_MAX_NUM;
    private Map<Long, List<Integer>> schedule = new HashMap<>();

    public long getCurrNum() { return currNum; }
    public void setCurrNum(long currNum) { this.currNum = currNum; }

    public long getMaxNum() { return maxNum; }
    public void setMaxNum(long maxNum) { this.maxNum = maxNum; }


    private List<Integer> scheduledAt(long num) {
        return schedule.computeIfAbsent(num, num_ -> new ArrayList<>());
    }

    private void scheduleNearest(Integer mod) {

        long nearestNum = currNum + (mod - currNum % mod);

        scheduledAt(nearestNum).add(mod);
    }

    public boolean add(Integer mod, String name) {

        if (modToName.containsKey(mod)) {
            return false;
        }

        modToName.put(mod, name);
        scheduleNearest(mod);

        return true;
    }

    public void addAll(Map<Integer, String> modToName) {

        for (Map.Entry<Integer, String> modAndName : modToName.entrySet()) {
            add(modAndName.getKey(), modAndName.getValue());
        }
    }


    @Override
    public Entry next() {

        List<Integer> currMods = scheduledAt(currNum);

        List<String> currNames = new ArrayList<>();

        for (Integer m : currMods) {

            String name = modToName.get(m);
            currNames.add(name);

            long newNum = currNum + m;
            scheduledAt(newNum).add(m);
        }

        Entry result = new Entry(currNum, currNames);

        currNum++;

        return result;
    }

    @Override
    public void remove() {
        schedule.remove(currNum - 1);
    }

    @Override
    public boolean hasNext() {
        return (maxNum < 0) || (currNum <= maxNum);
    }

    @Override
    public Iterator<Entry> iterator() {
        return this;
    }


    public static FizzBuzzer readFrom(InputStream in) {

        FizzBuzzer fizzBuzzer = new FizzBuzzer();

        try (Scanner scanner = new Scanner(in)) {

            long maxNum = scanner.nextLong();
            fizzBuzzer.setMaxNum(maxNum);

            while (scanner.hasNext()) {

                Integer mod = scanner.nextInt();
                scanner.skip("[\t ]*");
                String name = scanner.nextLine();

                fizzBuzzer.add(mod, name);
            }
        }

        return fizzBuzzer;
    }

    public void printTo(OutputStream out) {

        try (PrintWriter writer = new PrintWriter(out)) {

            for (FizzBuzzer.Entry e : this) {

                String strNames = String.join(" ", e.names);
                String line = String.format("%d %s", e.num, strNames);

                writer.println(line);
                writer.flush();

                remove();
            }
        }
    }

    @Override
    public String toString() {
        return String.format("%s; current %d; max %d",
                             modToName, currNum, maxNum);
    }
}

class GeneralFizzBuzz {

    public static void main(String[] args) {

        try {
            FizzBuzzer.readFrom(System.in).printTo(System.out);
        }

        catch (NoSuchElementException | IllegalStateException e) {

            System.err.format("Error: %s\n", e.toString());
            System.exit(1);
        }
    }
}