General FizzBuzz/jFizzBuzz: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Added more detailed error message.)
(→‎{{header|Java}}: Replaced the old joke with a new (fairy reasonable) implementation)
Line 1: Line 1:
<lang java>/**

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

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);
}
}
}</lang>

Revision as of 19:20, 11 June 2019

<lang java>/**

* @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);
       }
   }

}</lang>