keeping track of text based hangman game in an output file - java

Long story short, gameplayWord is a word that was randomly determined from a list of words for a hangman game read from (in this case the easy words file). easyContentList is an ArrayList of all the data in that file. The file is 2 columns, first col - the words that can be used, 2nd - a number representing how many times the word was used. (0 in the initial file) I need to keep track of this number based on each iteration of the game.
easyFileUpdateList is a String ArrayList declared at the class level.
Problem is this basically doesn't work:
public void updateEasyFile(String gameplayWord, ArrayList<String> easyContentList) {
Integer used = 0; // represents used word count
String strUsed = "";
for (int i = 0; i < easyContentList.size() - 1; i++) {
String oneLine;
oneLine = easyContentList.get(i);
tokenizer = new StringTokenizer(oneLine);
String firstToken = tokenizer.nextToken();
if (firstToken.equals(gameplayWord)) {
used = Integer.parseInt(tokenizer.nextToken());
used++;
strUsed = used.toString();
easyFileUpdateList.add(gameplayWord + " " + strUsed + " " + "TODO");
}
if (!firstToken.equals(tokenizer.nextToken())) // add the first token of every line except the first
easyFileUpdateList.add(oneLine);
}
try {
PrintWriter printWriter = new PrintWriter(new FileOutputStream(new File("hmeasy.txt")));
for (String oneLine : easyFileUpdateList) {
printWriter.println(oneLine);
}
printWriter.close();
}
catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
}
Update
Thank you, I will look into hash sets. Let me clarify a little more, I'm still not following completely.
Correct, the file will be as you said, so if the words are dog, cat, and fog the file will look like:
dog 0
cat 0
fog 0
There is a 3rd column of zeros, which is what the TODO is for but I'll worry about that later.
You are correct the problem that I am having is it is just adding a new entry with the word and then a 1 in the 2nd column. So if fog is randomly picked 3 times in a row and this method is executed it will say
dog 0
cat 0
fog 1
dog 0
cat 0
fog 1
fog 1
dog 0
cat 0
fog 1
fog 1
fog 1
what I'm looking for is:
first round:
dog 0
cat 0
fog 1
2nd round:
dog 0
cat 0
fog 2
etc...
I need to update the number in the file each time the word is randomly chosen.

Near as I can tell if your hmeasy.txt file looks like this:
firstGamePlayWord 0
secondGamePlayWord 0
And if the first entry is played it will soon look like this:
firstGamePlayWord 0
secondGamePlayWord 0
firstGamePlayWord 1 TODO
Which, I suspect, is not what you want. It's doing this because you use this line:
easyFileUpdateList.add(gameplayWord + " " + strUsed + " " + "TODO");
since this is an ArrayList add() just tacks that line at the end.
I could tell you to instead use set() with the i you worked so hard to find but that would be encouraging a bad design. You should stop using ArrayList for this. It wasn't designed for lookups.
Instead I encourage you to look at using a LinkedHashSet<String, Integer>. No need to tokenize, lookups will be fast, and everything will be in the same order it was added.
When trying to find the right data structure in java I look at this:

Thank you, I will look into hash sets. Let me clarify a little more, I'm still not following completely.
Correct, the file will be as you said, so if the words are dog, cat, and fog the file will look like:
dog 0
cat 0
fog 0
There is a 3rd column of zeros, which is what the TODO is for but I'll worry about that later.
You are correct the problem that I am having is it is just adding a new entry with the word and then a 1 in the 2nd column. So if fog is randomly picked 3 times in a row and this method is executed it will say
dog 0
cat 0
fog 1
dog 0
cat 0
fog 1
fog 1
dog 0
cat 0
fog 1
fog 1
fog 1
what I'm looking for is:
first round:
dog 0
cat 0
fog 1
2nd round:
dog 0
cat 0
fog 2
etc...
I need to update the number in the file each time the word is randomly chosen.

Related

Code chef :ODD , fastest way to calculate the nearest power of 2 for a given large number?

The link to the problem on codechef is:
http://www.codechef.com/problems/DCE05
The problem is:
The contestants have to stand in a line. They are given the numbers in the order in which they stand, starting from 1. The captain then removes all the contestants that are standing at an odd position.
Initially, standing people have numbers - 1,2,3,4,5...
After first pass, people left are - 2,4,...
After second pass - 4,....
And so on.
You want to board the ship as a crew member. Given the total number of applicants for a position, find the best place to stand in the line so that you are selected.
Input
First line contains the number of test cases t (t<=10^5). The next t lines contain integer n, the number of applicants for that case. (n<=10^9)
Output
Display t lines, each containing a single integer, the place where you would stand to win a place at TITANIC.
Example
Input:
2
5
12
Output:
4
8
I noticed a pattern:
For 1 : Output=1 (2^0)
For 2 : Output=2 (2^1)
For 3 : Output=2 (2^1)
For 4 : Output=4 (2^2)
For 5 : Output=4 (2^2)
For 6 : Output=4 (2^2)
For 7 : Output=4 (2^2)
For 8 : Output=8 (2^3) ans so on
So the answer every time is the nearest power of 2 which is <=number.
Here's my code:
import java.io.*;
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n=Integer.parseInt(br.readLine());
int x=0;
int output[]=new int[n];
for(int i = 0; i < n; i++)
{
output[i]=(int) Math.pow(2, Math.floor(Math.log(Integer.parseInt(br.readLine()))/Math.log(2)));
}
for(int i=0; i<n;i++)
{
System.out.println(output[i]);
}
}
}
Approach 1: I used Math.pow() to calculate powers of two in a loop until is becomes <= number , which I suppose was very inefficient.
Approach 2: I replaced Math.pow() with *2 in loop. (Still time exceeded)
Approach 3: I replaced multiplication by 2 with left shift in loop. (Still time exceeded)
Approach 4: I replaced loop with that log 2 logic, I found on stackverflow). (Still time exceeded)
Still it's showing time exceeded.
What is the fastest way to do this?
Be ensured that Integer.highestOneBit is the fastest part of your code. Even your original version was most probably way faster than parsing and formatting. I tried myself and succeeded with
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
if (sb.length() > 100000) {
System.out.print(sb);
sb.delete(0, sb.length());
}
final int x = Integer.parseInt(br.readLine());
final int y = Integer.highestOneBit(x);
sb.append(y).append("\n");
}
System.out.print(sb);
The computation is trivial, so I guessed the problem was the output and added some buffering. There's probably a simpler way, but I don't care.
Another possibility is that the site works non-deterministically and I was just lucky.

Comparing an array of item with two attributes

I met a question that I have problem solving in Java. The question goes like this:
John was asked to design a program that picks a bottle. The program has to decide from 4 bottles: Bottle A, B, C, D. There might be holes in some of the bottles. Therefore, the program must prevent picking bottles which have holes and also the largest bottle so as to carry as much water as possible.
Bottle A - has holes and can hold 5 litres of water
Bottle B - no holes and can hold 2 litres of water
Bottle C - no holes and can hold 3 litres of water
Bottle D - no holes and can hold 1 litre of water`
I have tried programming it in Java using a nested for loop. However, it does not give me the correct answers.
Bottle[] bottles = {a, b, c, d};
Bottle chosen = a;
for(int i=0; i<bottles.length; i++)
{
for(int j=i+1; j<bottles.length; j++)
{
if(bottles[i].capacity < bottles[j].capacity && bottles[j].noHoles())
{
chosen = bottles[j];
}
}
}
System.out.println(chosen.id);
First, since you are picking a single thing, all you need is a single loop. Second, since one of the properties (namely, noHoles()) is compared to a fixed value (i.e. it must be true) the only thing left for comparison is the capacity.
Hence, the algorithm looks like this:
Set the best bottle to null
Make a single loop that goes through bottles one by one
Check if the current bottle has no holes; if it does, continue the loop
Check if the best bottle is null. If it is, set best to current
Otherwise, compare the capacities of current and best, and set best to the bottle with larger capacity.
Your question is a little confusing so I am not sure if I answered what your asked. But if you only need to check if the Bottle has holes or not, you do not need to use nested for loops. I'd recommend use enhanced for loop. something like this:
for(Bottle bot : bottles){
if(bot.noHoles()) //i assume noHoles is bollean type
System.out.println(bot);
}
Try it as:
Bottle[] bottles = {a, b, c, d};
Bottle chosen = bottles[0];
for(int i=1; i<bottles.length; i++)
{
if(bottles[i].noHoles() && bottles[i].capacity > chosen.capacity)
chosen = bottles[i];
}
System.out.println(chosen.id);

Array and Java string error: [Ljava.lang.String;#19c42c4b

I've created a program that allows a user to enter in Journal entries (up to 7 days) and then allows a person to call up one of those days after they enter in an entry. Unfortunately, this has left me with some weird string error that I'm not familiar with.
Code as follows:
public class eDiary{
public static void main (String args[]){
int[] days = new int[7];//get our days
days[0] = 1;//start with 1 and not 0
days[1] = 2;
days[2] = 3;
days[3] = 4;
days[4] = 5;
days[5] = 6;
days[6] = 7;
String [] events = new String[7];//events for the days
int i = 0;
//asks for input and counts
for(i=0; i<7; i++){
String event = Console.readString("Tell me the major event of day " + days[i] + "\n");
events[i] = event;
}
int journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");
while (journal_entry != 0) {
System.out.println(events);
journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");
//get r dun!
The input and output:
Tell me the major event of day 1
one
Tell me the major event of day 2
two
Tell me the major event of day 3
thre
Tell me the major event of day 4
four
Tell me the major event of day 5
five
Tell me the major event of day 6
six
Tell me the major event of day 7
seven
Enter what day you want to hear or Enter 0 to stop
1
[Ljava.lang.String;#10181f5b
Enter what day you want to hear or Enter 0 to stop
0
Howdy y'all!
Thanks a lot for the quick responses. One thing it seems to be doing now is when replacing
System.out.println(events);
with
System.out.println(events[journal_entry]);
Now gives me input such as this:
Tell me the major event of day 1
first day
Tell me the major event of day 2
second day
Tell me the major event of day 3
third day
Tell me the major event of day 4
fourth day
Tell me the major event of day 5
fifth day
Tell me the major event of day 6
sixth day
Tell me the major event of day 7
seventh day
Enter what day you want to hear or Enter 0 to stop
1//the day im asking for
second day//spitting out the next day's entry instead of the first day's entry
Enter what day you want to hear or Enter 0 to stop
0//this is me stopping it
It's not an error.
System.out.println(events);
In this line you are trying to print the array, but that statement doesn't print the array contents, it only prints the object class name followed by its hashcode.
To print the array content you have to use
System.out.println(Arrays.toString(events));
Or, if you want, loop through the array and print its values
The [Ljava.lang.String;#10181f5b stuff is what you get when you explicitly or implicitly call Object.toString() and the target object's class doesn't override toString(). In this case, the issue is that Java array types do not override toString().
If you want to output an array, use java.util.Arrays.toString(...) to convert it to a String, then output that.
But in this case, you actually need to output a specific entry, not the entire array. The fix is to change
System.out.println(events);
to
System.out.println(events[journal_entry]);
For the record, the stuff above consists of the classes internal name ("[Ljava.lang.String;") and the object's identity hashcode (in hexadecimal).
This is not a "weird error string".
The output you are getting is because:
In Java, each object has toString() method, the default is displaying the class name representation, then adding # and then the hashcode.
You should use Arrays#toString(), which is implemented this way:
3860 public static String toString(int[] a) { {
3861 if (a == null)
3862 return "null";
3863 int iMax = a.length - 1;
3864 if (iMax == -1)
3865 return "[]";
3866
3867 StringBuilder b = new StringBuilder();
3868 b.append('[');
3869 for (int i = 0; ; i++) {
3870 b.append(a[i]);
3871 if (i == iMax)
3872 return b.append(']').toString();
3873 b.append(", ");
3874 }
3875 }
This will help you to better understand arrays.
Of course you can manually loop on the array and print it:
for(String event: events) {
System.out.println(event);
}
There is nothing wrong and that's not an error message.
Instead, it's the string representation of an array. Consider this line:
System.out.println(events);
You are printing the whole array, so you get that representation -- which happens to be a bit ugly, indeed. You want to print only one element, the one corresponding to the selected day. Use:
System.out.println(events[journal_entry]);
And perform bound checks.
This is not an error. You want to print the value of variable events. [Ljava.lang.String;#10181f5b means that events is an array of type java.lang.String and 10181f5b is hashcode of this variable. What you want to println is event[i] where i is the number of a day.
In java array's are consider as object. you are printing the event array object that's not what you want.
You need to print name of the day in a week. You need to replace
System.out.println(events);
to
System.out.println(events[journal_entry]);
It won't print out the answer correctly because you just pointed System.out.println() to events which is supposed to be an array pointer and not the actual variable. You should just replace this line with
System.out.println(events[journal_entry]);
For it to make sense. Run it with the conmmand and see if it will run properly.
Thanks for all the responses! I was able to resolve the issue. Here's the code if anyone is curious:
public static void main (String args[]){
int[] days = new int[7];//get our days
days[0] = 1;//start with 1 and not 0
days[1] = 2;
days[2] = 3;
days[3] = 4;
days[4] = 5;
days[5] = 6;
days[6] = 7;
String [] events = new String[7];//events for the days
int i = 0;
//asks for input and counts
for(i=0; i<7; i++){
String event = Console.readString("Tell me the major event of day " + days[i] + "\n");
events[i] = event;
int journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");
while (journal_entry != 0) {
System.out.println("On day " + days[i = 0] + " " + events[journal_entry - 1]);
journal_entry = Console.readInt("Enter what day you want to hear or Enter 0 to stop \n");

Last line only partially prints in Java

I have some java code that compares two files. When it finds similar numbers on a particular line it prints that line to a new file. This seems to work for a good amount of time... Until what I believe is the last line. That line only ever gets partially printed. I THINK that it might be because of a 'break' that is later in the code, but I looked around on google and wasn't really sure if any of the answers were really relevant.
Here is some code that I think is related:
Read in files
while the line isn't null...
Parse files
Write a header
Some comparisons
while (!input.startsWith("#") && !input.startsWith("P")) {
prse = input.split("\t");//split the file by tabs
pos = prse[7];
poson = prse[8];
pos = Integer.parseInt(poson);
if (cnt < num.size()) { //if we haven't exceeded an array
if (num.get(cnt).equals(pos)) { //if the first number is the same
if (cnt2 < posstart.size()) { //if we haven't exceeded another array
end = Integer.parseInt(posend.get(cnt2)); //change to int
start = Integer.parseInt(posstart.get(cnt2));//change to int
if (pos < start) { //if it is less then the starting pos then it can't fall within
break; //so break
}
if (pos < end && pos > start) {//I am trying to see if a number falls within the range of numbers from a separate file
out1.write(input + "\n"); //If it does: This is where I am writing out the line
break; //if I remove this break the program hangs here
} else {
cnt2++; //if it wasn't the same, add
}
}
} else {
cnt++; //if it was the same move to the next one
cnt2 = 0; //reset this number
break; //go back to beginning
}
} else {
break;
}
So the code works perfectly for about 6500 lines but then it abruptly cuts off the last line:
Blah B 6 5 8 C 5 X 6
Blah A 0 1 4 C 2 X 7
Blah B 3 5 9 C 5 X 6
Blah B 0 9 4
Does anyone know what I can add to stop the final line from cutting off so suddenly? I know in BASH you could specify for it to wait... But I was confused by the java equivalents and was hoping someone could suggest one for me and help to explain it a bit better.
For the sake of having an answer (until Carl puts his up) I am going to go ahead and answer
did you close the outputstream? maybe you need to call the flush method. – Carl
He was right. I hadn't. Silly me.
Actually, i made that mistakes a lot, i think it is because with the garbage collector,we don't really care about memory management,so,it tends to forget to close any iostream we'd opened or to flush memory to disk.That's a terrible thing to do though.

Very basic stuff: having trouble with a program simulating a slot machine- enums and arrays

So my professor gave out an assignment in which we have to create an operating slot machine program. The machine has 3 reels, which themselves consist of 6 six symbols stored in an enum:
public enum Symbol
{
SEVEN(12,"images/seven.jpg"),
WATERMELON(10,"images/watermelon.jpg"),
ORANGE(8,"images/orange.jpg"),
PLUM(6,"images/plum.jpg"),
LEMON(4,"images/lemon.jpg"),
CHERRY(2,"images/cherry.jpg");
}
We're supposed to use these symbols to create a "reel" object. My problem is centered around populating this reel (which is really just a Symbol[] array) with the symbols in the order requested by the professor.
He asked us to use the Random class to populate the reel using 10 as the seed number. Here's what I have so far:
//Creating an unrandomized reel array, which contains the symbols in the exact order as they appear in the enum
private Symbol[] unrandomizedReel = new Symbol[]{Symbol.SEVEN, Symbol.WATERMELON, Symbol.ORANGE, Symbol.PLUM, Symbol.LEMON, Symbol.CHERRY};
//Declares local Symbol array
Symbol[] randomizedReel = new Symbol[6];
//Keeps track of the position in the unradomized reel array
int unrandomizedReelIndex = 0;
//Creates a Random object which will be used to generate values based
//on the seed. **seed == 10**
Random randNum = new Random(seed);
//Loop will populate the randomized reel
while(unrandomizedReelIndex < 6)
{
//This int will hold values ranging from 0-5. Will be used as an index
//to populate randomized reel
int rangedRandomNumIndex = randNum.nextInt(6);
//if the element at the given index in the randomized reel is empty
if(randomizedReel[rangedRandomNumIndex] == null)
{
//A symbol from the unrandomized reel is added to it
randomizedReel[rangedRandomNumIndex] = unrandomizedReel[unrandomizedReelIndex];
//The index used to iterate through the unrandomized reel is incremented by 1
unrandomizedReelIndex++;
}
}
Running this "shuffling" code, I get the following output:
WATERMELON
PLUM
CHERRY
SEVEN
ORANGE
LEMON
However, according to my professor, the output should be:
ORANGE
PLUM
SEVEN
LEMON
WATERMELON
CHERRY
What am I doing wrong? Why is my output different from his, even though we are both using 10 as a seed? Any help would be appreciated. Thanks.
new Symbol[]{Symbol.SEVEN, Symbol.WATERMELON, Symbol.ORANGE, Symbol.PLUM, Symbol.LEMON, Symbol.CHERRY};
can be simplified to
Symbol.values()
My guess would be that your professor is putting
unrandomizedReel[Random.nextInt(6)]
in position 0, then nulling that out that element of unrandomizedReel, getting a random number x between 1 and 5 and taking the x-th non-null value and putting it in position 1, nulling it, then repeating with a number between 1 and 4 and so on.
If you have a reason to believe your professor is using a different algo, then edit your question with that information.

Categories