I've been tasked to write a basic guessing game, which I have done, but part of the task is confusing me. We've been asked to create a warning when a user inputs the same guess too many times. I've tried several ways to take the previous user guess and compare them with the current one but none seem to work. Can anyone help me with this? My Google skills seem to have failed me.
Mostly I've tried this:
void guessWarning(int confirmedGuess){
int prevGuess = currentGuess;
int currentGuess = confirmedGuess;
if(prevGuess == currentGuess){
text("Same guess, try again",350,350)
}
}
There are multiple ways to tackle this.
One option would be keep track of the previous attempts in a dynamic array (see ArrayList). Here a bit of code to illustrate the concept:
//create a new list of integers
ArrayList<Integer> guesses = new ArrayList<Integer>();
//in your check function, test if the new value already exists
if(guesses.contains(NEW_GUESS_HERE)){
println("you've already tried this number");
}else{//otherwise add the current guess to keep track of for next time
guesses.add(NEW_GUESS_HERE);
}
Another option is using a HashMap. This is an associative array as opposed to an index based array. This method is more efficient and you can also keep track of how many attempts there were for each value. Be sure to read more on HashMaps: it will help you on the long run and potentially impress your tutors on the short run.
Here's a basic sketch to illustrate the idea:
//create a new hashmap of integers (key = guess, value = number of times tried)
HashMap<Integer,Integer> guesses = new HashMap<Integer,Integer>();
int answer = '=';
void setup(){}
void draw(){}
void keyPressed(){
guess(keyCode);
println(keyCode);
}
void guess(int newValue){
if(newValue == answer){
println("you guessed it!");
}else{
//check if the value was already recorded
try{
//if there was a value with this key, it's been tried before
int numberOfTries = guesses.get(newValue);
println("you've tried this value",numberOfTries,"times");
//increment the number of times this has beeen attempted
guesses.put(newValue,numberOfTries+1);
}catch(NullPointerException e){
println("it's the first time you try this number, but you haven't guessed it yet");
guesses.put(newValue,1);
}
}
}
A similar option, but a bit more hacky would be using a JSONObject.
The concept is similar: an associative array (albeit the key is a string, instead of an int), but you'd need to convert the guessed number to a string to index it first:
JSONObject guesses = new JSONObject();
int answer = '=';
void setup(){}
void draw(){}
void keyPressed(){
guess(keyCode);
println(keyCode);
}
void guess(int newValue){
if(newValue == answer){
println("you guessed it!");
}else{
//hacky int to string
String newValueStr = newValue+"";
//check if the value was already recorded
if(guesses.hasKey(newValueStr)){
//if there was a value with this key, it's been tried before
int numberOfTries = guesses.getInt(newValueStr);
println("you've tried this value",numberOfTries,"times");
//increment the number of times this has beeen attempted
guesses.setInt(newValueStr,numberOfTries+1);
}else{
println("it's the first time you try this number, but you haven't guessed it yet");
guesses.setInt(newValueStr,1);
}
}
}
One nice thing is that you could save the guesses to disk, then load it so the program could recall previous guesses even if the it was restarted.
I'll leave you the fun exercise of attempting to load the data when the sketch starts and saving the data when the sketch exists.
Related
I'm trying to implement a "search as you type" pattern in Java.
The goal of the design is that no change gets lost but at the same time, the (time consuming) search operation should be able to abort early and try with the updated pattern.
Here is what I've come up so far (Java 8 pseudocode):
AtomicReference<String> patternRef
AtomicLong modificationCount
ReentrantLock busy;
Consumer<List<ResultType>> resultConsumer;
// This is called in a background thread every time the user presses a key
void search(String pattern) {
// Update the pattern
synchronized {
patternRef.set(pattern)
modificationCount.inc()
}
try {
if (!busy.tryLock()) {
// Another search is already running, let it handle the change
return;
}
// Get local copy of the pattern and modCount
synchronized {
String patternCopy = patternRef.get();
long modCount = modificationCount.get()
}
while (true) {
// Try the search. It will return false when modificationCount changes before the search is finished
boolean success = doSearch(patternCopy, modCount)
if (success) {
// Search completed before modCount was changed again
break
}
// Try again with new pattern+modCount
synchronized {
patternCopy = patternRef.get();
modCount = modificationCount.get()
}
}
} finally {
busy.unlock();
}
}
boolean doSearch(String pattern, long modCount)
... search database ...
if (modCount != modificationCount.get()) {
return false;
}
... prepare results ...
if (modCount != modificationCount.get()) {
return false;
}
resultConsumer.accept(result); // Consumer for the UI code to do something
return modCount == modificationCount.get();
}
Did I miss some important point? A race condition or something similar?
Is there something in Java 8 which would make the code above more simple?
The fundamental problem of this code can be summarized as “trying to achieve atomicity by multiple distinct atomic constructs”. The combination of multiple atomic constructs is not atomic and trying to reestablish atomicity leads to very complicated, usually broken, and inefficient code.
In your case, doSearch’s last check modCount == modificationCount.get() happens while still holding the lock. After that, another thread (or multiple other threads) could update the search string and mod count, followed by finding the lock occupied, hence, concluding that another search is running and will take care.
But that thread doesn’t care after that last modCount == modificationCount.get() check. The caller just does if (success) { break; }, followed by the finally { busy.unlock(); } and returns.
So the answer is, yes, you have potential race conditions.
So, instead of settling on two atomic variables, synchronized blocks, and a ReentrantLock, you should use one atomic construct, e.g. a single atomic variable:
final AtomicReference<String> patternRef = new AtomicReference<>();
Consumer<List<ResultType>> resultConsumer;
// This is called in a background thread every time the user presses a key
void search(String pattern) {
if(patternRef.getAndSet(pattern) != null) return;
// Try the search. doSearch will return false when not completed
while(!doSearch(pattern) || !patternRef.compareAndSet(pattern, null))
pattern = patternRef.get();
}
boolean doSearch(String pattern) {
//... search database ...
if(pattern != (Object)patternRef.get()) {
return false;
}
//... prepare results ...
if(pattern != (Object)patternRef.get()) {
return false;
}
resultConsumer.accept(result); // Consumer for the UI code to do something
return true;
}
Here, a value of null indicates that no search is running, so if a background thread sets this to a non-null value and finds the old value to be null (in an atomic operation), it knows it has to perform the actual search. After the search, it tries to set the reference to null again, using compareAndSet with the pattern used for the search. Thus, it can only succeed if it has not changed again. Otherwise, it will fetch the new value and repeat.
These two atomic updates are already sufficient to ensure that there is only a single search operation at a time while not missing an updated search pattern. The ability of doSearch to return early when it detects a change, is just a nice to have and not required by the caller’s loop.
Note that in this example, the check within doSearch has been reduced to a reference comparison (using a cast to Object to prevent compiler warnings), to demonstrate that it can be as cheap as the int comparison of your original approach. As long as no new string has been set, the reference will be the same.
But, in fact, you could also use a string comparison, i.e. if(!pattern.equals(patternRef.get())) { return false; } without a significant performance degradation. String comparison is not (necessarily) expensive in Java. The first thing, the implementation of String’s equals does, is a reference comparison. So if the string has not changed, it will return true immediately here. Otherwise, it will check the lengths then (unlike C strings, the length is known beforehand) and return false immediately on a mismatch. So in the typical scenario of the user typing another character or pressing backspace, the lengths will differ and the comparison bail out immediately.
I was wondering how I would go about getting a different set of data to print every time I press the same key for KeyPressed in Processing. The data being displayed is from an imported file so the code for what I'm doing is as follows:
import java.util.Scanner;
import java.io.*;
PImage cityMap;
FileInputStream in;
int Year=0;
void setup()
{
size(500,500);
cityMap=loadImage("cityMap.png");
background(cityMap);
}
void draw()
{
//EMPTY
}
void keyPressed() {
if(key==CODED)
{
if(keyCode==RIGHT)
{
//2015
String fif[]= loadStrings("2015data.txt");
for (int i=1; i<fif.length;i++)
{
Scanner sc= new Scanner(fif[i]);
int xValue= sc.nextInt();
int yValue= sc.nextInt();
int pixelX= locX2PixX(xValue);
int pixelY= locY2PixY(yValue);
stroke(200,200,250);
point(pixelX,pixelY);
}
//2016
String six[]= loadStrings("2016data.txt");
if(
for (int i=1; i<six.length;i++)
{
Scanner sc= new Scanner(six[i]);
int xValue= sc.nextInt();
int yValue= sc.nextInt();
int pixelX2= locX2PixX(xValue);
int pixelY2= locY2PixY(yValue);
stroke(250,200,250);
point(pixelX2,pixelY2);
}
//2017
String seven[]= loadStrings("2017data.txt");
for (int i=1; i<seven.length;i++)
{
Scanner sc= new Scanner(seven[i]);
int xValue= sc.nextInt();
int yValue= sc.nextInt();
int pixelX3= locX2PixX(xValue);
int pixelY3= locY2PixY(yValue);
stroke(20,200,250);
point(pixelX3,pixelY3);
}
}
}
}
int locX2(int locationX)
{
return((int)((6*locationX)-8));
}
int locY2(int locationY)
{
return((int)(8*locationY+8));
}
I managed to get the code to run minus that one feature.
I think I have most of the logic down, I'm just trying to figure out to have this show only one set of the data at a time and then the next one after I press the same key again. I was thinking I may need some type of if statement that could maybe use my year variable?
(I don't know that much about Processing, but it's silly to chat in comments about general purpose computer programming...)
It sounds like you need to maintain "state", which is a fancy way of saying a variable where you store information about if you have done something before, and what that thing is.
First, how many states do you care about? It sounds like you have two distinct options, so if you add the initial state, this technically makes three (but for only two valid states we can ignore that for now). Ok, so your startup code (constructor or initializer, whatever is typical for Processing) will set a variable of some sort to a known start value.
How to do this is up to you. It could be a String or an int or something advanced like an enum. The idea is that this is a testable, settable, persistent chunk of data that you know the meaning of.
Every time you handle the "event" of a button being pushed you do two things:
Test the state you initialized earlier and make a decision. In the initial state you want to load "2015" data. Ok. So do that.
Change the variable holding the state so it is in the "next" state. In the 2015 state we want to change that to 2016 so we are ready for the next button event we handle.
A simple example would be to create an int called dataState or something. In setup set this to 2015. In your button handler have a switch or if statement that checks for all possible values dataState can be, and runs the appropriate code for that state. e.g., if it is set to 2015 it will do whatever you need it to do for 2015, but at the end it should set the dataState to 2016 so that the next time through it does the 2016 branch.
It is up to you what the 2016 branch does to this state. You can reset it to 2015 or continue on to 2017, if your code needs to have that functionality.
Some comments:
You'll notice that your code for processing 2015 data is almost the same as the code that processes 2016 data. This is an opportunity to use a function or method that accepts a filename and does some work based on that, and then sets the state to the "next" state.
Once you do this, then your logic in the button handler becomes a nice short and understandable set of if ... else if statements that simply call the appropriate function for that state. This makes it easy to add, say, 2017 processing. Code always grows features so it's good to plan ahead for that.
Once you get really good at this, you'll start thinking about "state models" and then before you know it you'll want to have your state managed as a class or enum with a big switch statement that drives the whole works. This is a very common pattern with embedded, event driven code that Processing supports.
keep track of your year in a variable and change it when the key is pressed. Something like this
//start off one less than first desired year
int Year=2014;
void keyPressed() {
if(key==CODED) {
if(keyCode==RIGHT) {
//increment year
Year = Year+1;
//Clamp year between 2015 and 2017
Year= Math.max(2015, Math.min(2017, Year));
String yr[]= loadStrings(Year +"data.txt");
for (int i=1; i<yr.length;i++) {
Scanner sc= new Scanner(yr[i]);
int xValue= sc.nextInt();
int yValue= sc.nextInt();
int pixelX= locX2PixX(xValue);
int pixelY= locY2PixY(yValue);
stroke(200,200,250);
point(pixelX,pixelY);
}
}
}
}
I am trying to create a method that will take a list of items with set weights and choose 1 at random. My solution was to use a Hashmap that will use Integer as a weight to randomly select 1 of the Keys from the Hashmap. The keys of the HashMap can be a mix of Object types and I want to return 1 of the selected keys.
However, I would like to avoid returning a null value on top of avoiding mutation. Yes, I know this is Java, but there are more elegant ways to write Java and hoping to solve this problem as it stands.
public <T> T getRandomValue(HashMap<?, Integer> VALUES) {
final int SIZE = VALUES.values().stream().reduce(0, (a, b) -> a + b);
final int RAND_SELECTION = ThreadLocalRandom.current().nextInt(SIZE) + 1;
int currentWeightSum = 0;
for (Map.Entry<?, Integer> entry : VALUES.entrySet()) {
if (RAND_SELECTION > currentWeightSum && RAND_SELECTION <= (currentWeightSum + entry.getValue())) {
return (T) entry.getKey();
} else {
currentWeightSum += entry.getValue();
}
}
return null;
}
Since the code after the loop should never be reached under normal circumstances, you should indeed not write something like return null at this point, but rather throw an exception, so that irregular conditions can be spotted right at this point, instead of forcing the caller to eventually debug a NullPointerException, perhaps occurring at an entirely different place.
public static <T> T getRandomValue(Map<T, Integer> values) {
if(values.isEmpty())
throw new NoSuchElementException();
final int totalSize = values.values().stream().mapToInt(Integer::intValue).sum();
if(totalSize<=0)
throw new IllegalArgumentException("sum of weights is "+totalSize);
final int threshold = ThreadLocalRandom.current().nextInt(totalSize) + 1;
int currentWeightSum = 0;
for (Map.Entry<T, Integer> entry : values.entrySet()) {
currentWeightSum += entry.getValue();
if(threshold <= currentWeightSum) {
return entry.getKey();
}
}
// if we reach this point, the map's content must have been changed in-between
throw new ConcurrentModificationException();
}
Note that the code fixes some other issues of your code. You should not promise to return an arbitrary T without knowing the actual type of the map. If the map contains objects of different type as key, i.e. is a Map<Object,Integer>, the caller can’t expect to get anything more specific than Object. Besides that, you should not insist of the parameter to be a HashMap when any Map is sufficient. Further, I changed the variable names to adhere to Java’s naming convention and simplified the loop’s body.
If you want to support empty maps as legal input, changing the return type to Optional<T> would be the best solution, returning an empty optional for empty maps and an optional containing the value otherwise (this would disallow null keys). Still, the supposed-to-be-unreachable code point after the loop should be flagged with an exception.
I have to come up with a Class and Data Structure Design for a "metric" system to determine the top song of a * band..
The class should have Two Web Service calls
void play(String bandname, String songname);/*This method has to play song with the requested brandname and songname. Also have to keep track of the song payed count to support the below method.*/
String topSong(String bandname);/* This method has to play mostly played song under the requested brand*/
Sample inputs:
BrandName:"Lady Gaga", Song : "Pokerface";
BrandName:"Lady Gaga", Song : "Pokerface";
BrandName:"Lady Gaga", Song : "Alejandro";
BrandName:"Bruno Mars",Song : "Treasure";
Please advice!
If I understand correctly, you need to maintain a dictionary, where key is band name and value is a priority queue. Each object inside priority queue will have "song name" and "play count" attributes and priority queue needs to be sorted by "play count" attributes. Each time a song is played, increment it's play count and heapify the queue.
Doing the above is a bit complicated and based on programming languages, implementation approach might vary wildly. You shouldn't do this unless the number of songs of a band can be huge, which is pretty unlikely.
Anyway, that's practical implementation detail. The text book answer for questions like these is always priority queue.
If kept in memory, this looks like a job for a hash table, associative array, or dictionary. If kept in a persistent store, a database would be the easiest way to go.
You need two storages.
A dictionnary that maps bandname to it's top songname. Let's call it topBandSong.
A dictionnary that maps (bandname, songname) to the number of times this song has been played. Let's call it bandSongPopularity.
With this topSong is pretty simple (leaving aside the case where nothing is known about the band yet):
Map<String, String> topBandSong = new HashMap();
String topSong(String bandname) {
return topBandSong.get(bandname);
}
The play function has to update both maps. This is really easy:
Map<String, BigInteger> bandSongPopularity = new HashMap();
void play(String bandname, String songname) {
/* First update bandSongPopularity */
String k = bandname + "\000" + songname;
BigInteger popularity = bandSongPopularity.get(k);
if (popularity == null) {
popularity = BigInteger.valueOf(1);
}
else {
popularity = popularity.add(BigInteger.valueOf(1));
}
bandSongPopularity.put(k, popularity);
/* then update topBandSong */
String top = topSong(bandname);
if (top == null) {
topBandSong.put(bandname, songname);
}
else {
String topK = bandname + "\000" + top;
BigInteger topPopularity = bandSongPopularity.get(topK);
/* topPopularity can not be NULL */
if (popularity.compareTo(topPopularity) > 0) {
topBandSong.put(bandname, songname);
}
}
/* Finally really play this song. But this is left as an exercise ;-) */
}
The complexity is the one of the underlying dictionnary you choose, i.e. a tree or a hash.
Note that the code reserves character number 0.
I've done some elementary coding in the past, and I'm now learning Unity and trying some things with C#.
My problem:
I have a list of objects that have their own id number in the range of 1-50. I want my game to pick one object at random instead of going over the list in order. The first step would be to pick the initial id to be some random number, but I only get the error: "error CS1729: The type UnityEngine.Random' does not contain a constructor that takes1' arguments". I understand that I should give more argument for the constructor, but I need help in seeing how, since the code looks fine (if simple) to me.
Anyway, it goes like this at the moment:
public int id;
public int randomid;
public void RandId(int id)
{
Random randomid = new Random(Random.Range(1, 51));
id = randomid;
return id;
}
Here id is the identification number of the objects, randomid is for randomizing it, and I use Random.Range to create the wanted range (1-50). It seems I need to give more arguments to Random.Range, but it already has both min and max.
Can you give me some advice?
There are some other things wrong w/ your code, but this should be what you need.
public void SetIDToRandom(out int id)
{
id = (int)Random.Range(1, 51);
}
Addendum:
Random is a static class, you don't directly instantiate it.