ive been working on a java compiler assignment that is asking to find the First of a grammar. I have it all ready and done. all the work has been done , but i have one problem. my first is producing duplicates. for example part of my output is this
NonTerminal First
P int void
L int void
D int void
Vd int void
Ts int void
Fn int void
Ps int void void
Ps int void void , the 2nd void is a duplicate. how would i go about removing these duplicates? ill paste my main compiler code were everything happens below.
i suspect i would have to make a change somewere in the findFirst method, since thats were all the action happens , but im not sure what to do.
package compilerproject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.security.KeyStore.Entry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Compiler {
public static void main(String[] args) {
List<Grammar> gList = getGrammar();
Map<String, List<String>> fList = firstList(gList);
//firstlist returns a hash map LHS and RHS
//save it into fList which is a map of Strings and List so u can use it in findFirst method
printFirstList(fList, gList);
ParserLibrary idList = new ParserLibrary();
}
public static List<String> findFirst(String v, List<Grammar> l)
{
List<String> First = new ArrayList<String>();
for(int i = 0; i < l.size(); i++)
{
if(v.equals(l.get(i).term))
{
String [] s = l.get(i).prod.split(" ");
if(!isNonTerm(s[0]))// is a terminal
{
First.add(s[0]);
}
// if the rhs is a terminal
It would save some troubles using a Set instead of a List.
I kept List as return type, but changed the rest.
public static List<String> findFirst(String v, List<Grammar> l) {
Set<String> first = new TreeSet<>();
Set<String> done = new HashSet<>();
done.add(v);
Grammer previous = null;
for (Grammar gr : l) {
if (v.equals(gr.term)) {
String s = gr.prod.split(" ")[0];
if (!isNonTerm(s)) { // is a terminal
first.add(s);
}
// if the rhs is a terminal
if (s.equalsIgnoreCase("empty") && previous != null) {
String[] stemp = previous.prod.split(" ");
if (v.equalsIgnoreCase(stemp[0]) && stemp.length > 1
&& done.add(stemp[1])) {
first.addAll(findFirst(stemp[1], l)); // <--------- Here it happened
}
//if the rhs is empty , then get the previous grammar
//split it.
//find the first of it and ad it to the first list
}
if (!v.equals(s) && isNonTerm(s) && done.add(s)) {
first.addAll(findFirst(s, l));
}
}
previous = gr;
}
return new ArrayList<String>(first);
}
I still do not find the code entirely clear. So maybe with Set at your disposal, you may find a simpler formulation. To remove the scroll bar I place the open brace on the same line.
To prevent endless recursion I added the set done which "evidently" is not needed.
Related
I am new to parallel stream and trying to make 1 sample program that will calculate value * 100(1 to 100) and store it in map.
While executing code I am getting different count on each iteration.
I may be wrong at somewhere so please guide me anyone knows the proper way to do so.
code:
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.stream.Collectors;
public class Main{
static int l = 0;
public static void main (String[] args) throws java.lang.Exception {
letsGoParallel();
}
public static int makeSomeMagic(int data) {
l++;
return data * 100;
}
public static void letsGoParallel() {
List<Integer> dataList = new ArrayList<>();
for(int i = 1; i <= 100 ; i++) {
dataList.add(i);
}
Map<Integer, Integer> resultMap = new HashMap<>();
dataList.parallelStream().map(f -> {
Integer xx = 0;
{
xx = makeSomeMagic(f);
}
resultMap.put(f, xx);
return 0;
}).collect(Collectors.toList());
System.out.println("Input Size: " + dataList.size());
System.out.println("Size: " + resultMap.size());
System.out.println("Function Called: " + l);
}
}
Runnable Code
Last Output
Input Size: 100
Size: 100
Function Called: 98
On each time run output differs.
I want to use parallel stream in my own application but due to this confusion/issue I can't.
In my application I have 100-200 unique numbers on which some same operation needs to be performed. In short there's function which process something.
Your access to both the HashMap and to the l variable are both not thread safe, which is why the output is different in each run.
The correct way to do what you are trying to do is collecting the Stream elements into a Map:
Map<Integer, Integer> resultMap =
dataList.parallelStream()
.collect(Collectors.toMap (Function.identity (), Main::makeSomeMagic));
EDIT: The l variable is still updated in a not thread safe way with this code, so you'll have to add your own thread safety if the final value of the variable is important to you.
By putting some values in resultMap you're using a side-effect:
dataList.parallelStream().map(f -> {
Integer xx = 0;
{
xx = makeSomeMagic(f);
}
resultMap.put(f, xx);
return 0;
})
The API states:
Stateless operations, such as filter and map, retain no state from
previously seen element when processing a new element -- each element
can be processed independently of operations on other elements.
Going on with:
Stream pipeline results may be nondeterministic or incorrect if the
behavioral parameters to the stream operations are stateful. A
stateful lambda (or other object implementing the appropriate
functional interface) is one whose result depends on any state which
might change during the execution of the stream pipeline.
It follows an example similar to yours showing:
... if the mapping operation is performed in parallel, the results for
the same input could vary from run to run, due to thread scheduling
differences, whereas, with a stateless lambda expression the results
would always be the same.
That explains your observation: On each time run output differs.
The right approach is shown by #Eran
Hopefully it works fine. by making Synchronied function makeSomeMagic and using Threadsafe data structure ConcurrentHashMap
and write simple statement
dataList.parallelStream().forEach(f -> resultMap.put(f, makeSomeMagic(f)));
Whole code is here :
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.stream.Collectors;
public class Main{
static int l = 0;
public static void main (String[] args) throws java.lang.Exception {
letsGoParallel();
}
public synchronized static int makeSomeMagic( int data) { // make it synchonized
l++;
return data * 100;
}
public static void letsGoParallel() {
List<Integer> dataList = new ArrayList<>();
for(int i = 1; i <= 100 ; i++) {
dataList.add(i);
}
Map<Integer, Integer> resultMap = new ConcurrentHashMap<>();// use ConcurrentHashMap
dataList.parallelStream().forEach(f -> resultMap.put(f, makeSomeMagic(f)));
System.out.println("Input Size: " + dataList.size());
System.out.println("Size: " + resultMap.size());
System.out.println("Function Called: " + l);
}
}
There is no need to count how many times the method invoked.
Stream will help you do loop in byte code.
Pass your logic(function) to Stream, do not use no thread-safe variable in multi-thread(include parallelStream)
like this.
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ParallelStreamClient {
// static int l = 0;---> no need to count times.
public static void main(String[] args) throws java.lang.Exception {
letsGoParallel();
}
public static int makeSomeMagic(int data) {
// l++;-----> this is no thread-safe way
return data * 100;
}
public static void letsGoParallel() {
List<Integer> dataList = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
dataList.add(i);
}
Map<Integer, Integer> resultMap =
dataList.parallelStream().collect(Collectors.toMap(i -> i,ParallelStreamClient::makeSomeMagic));
System.out.println("Input Size: " + dataList.size());
System.out.println("Size: " + resultMap.size());
//System.out.println("Function Called: " + l);
}
import acm.program.*;
import java.util.*;
public class ReverseArrayList extends ConsoleProgram {
public void run() {
println("This program reverses the elements in an ArrayList.");
println("Use 0 to signal the end of the list.");
ArrayList<Integer> list = readArrayList();
reverseArrayList(list);
printArrayList(list);
}
/* Reads the data into the list */
private ArrayList<Integer> readArrayList() {
ArrayList<Integer> list = new ArrayList<Integer>();
while (true) {
int value = readInt(" ? ");
if (value == 0) break;
list.add(value);
}
return list;
}
I dont understand the following code:
ArrayList<Integer> list = readArrayList();
I dont understand why I can't do the following instead:
list.getInput();
Why do i need to make the ArrayList equal to the method, and this confuses me because now I'm unsure which way is needed whenever I want to call a method in java
Your code shows that the method getInput() does not take in an ArrayList as argument, but returning it instead. So it is reasonable that
Arrlist=getInput()
Is the correct syntax, you are assigning the returned ArrayList from getInput() to Arrlist. While on the other hand,
Arrlist.getInput()
represents a method that must be implemented in ArrayList Class or one of its superclasses, which is not true in your case. I would recommend revising OOP concepts.
One way you might be able to pass it is using a constructor. I mocked up working code that does the same.
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ArrayListExample {
ArrayList<Integer> ofNumbers;
public ArrayListExample() {
ofNumbers = new ArrayList<>();
createArray();
}
private void createArray(){
ofNumbers = IntStream.range(0, 10)
.boxed()
.collect(Collectors
.toCollection(ArrayList::new));
}
public ArrayList<Integer> getInput() {
return ofNumbers;
}
public void getArray() {
ArrayList<Integer> newList = new ArrayList<>(ofNumbers);
for (Integer num : newList) {
System.out.println(num);
}
}
}
I also agree with Andrew. Keep it up, with a little more practice this will become second nature to you.
I am creating a Java program that reads two text files, selects 10 words at random from each file and stores them in an array of two string lists. I have created the following code so far, however this only reads the words, it doesn't store them. I also need to serialize the array of 2 lists in a binary file. How can this be done? Some help with this would be greatly appreciated!
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
import static java.nio.file.StandardOpenOption.CREATE;
public class RandomWordGenerator {
public static void main(String[] args) throws IOException {
Path outputFile = Paths.get("output.txt");
ArrayList<String> randomWords1 = randomWordsFromFile("input1.txt", 10);
ArrayList<String> randomWords2 = randomWordsFromFile("input2.txt", 10);
OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(outputFile, CREATE));
System.out.println(randomWords1);
System.out.println(randomWords2);
outputStream.flush();
for (int i = 0; i < randomWords1.size(); i++) {
outputStream.write(randomWords1.get(i).getBytes());
}
for (int i = 0; i < randomWords2.size(); i++) {
outputStream.write(randomWords2.get(i).getBytes());
}
outputStream.close();
}
private static ArrayList<String> randomWordsFromFile(String fileName, int count) throws FileNotFoundException {
Scanner scanner = new Scanner(new File(fileName));
ArrayList<String> words = new ArrayList<>();
while (scanner.hasNext()) {
words.add(scanner.next());
}
return randomFromWords(words, count);
}
static private ArrayList<String> randomFromWords(ArrayList<String> words, int count) {
ArrayList<String> randomWords = new ArrayList<>();
for (int i = 0; i < count; ) {
int random = new Random().nextInt(words.size());
if (randomWords.add(words.get(random))) {
i++;
}
}
return randomWords;
}
}
Your code should read two files, select ten random words from each file and store the ten words from each file into two lists. Does it do this correctly? If it does not then fix all the errors before proceeding further. You can ask here with specific errors you cannot fix. Be sure to explain what your code is meant to do, and the error it makes to prevent it doing that.
Once everything is working correctly, go on to the next stage. Is the binary Serialization part of your requirement? If not, then I would use a simple CSV file in UTF-8, which is also a binary file (as are all files at heart). If actual Serialization is required, then read the Javadocs and tutorials on Serialization. Write some code and come back here if you cannot get it to work.
I was trying to print all n roots of a complex number in x+iy format . I am using Apache Common Math . Here is my code:
package complex;
import static java.lang.String.format;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.complex.ComplexFormat;
public class Do
{
public static void main(String[] args)
{
ComplexFormat complexFormat = new ComplexFormat();
Complex r = new Complex(6.3,9.6);
List<Object> list = new ArrayList();
list.add(r.nthRoot(8));
List list2 = new ArrayList();
for(int i=list.size()-1;i>=0;i--)
{
String c = (list.get(i).toString());
list2.add(c);
}
System.out.println(Arrays.toString(list2.toArray()));
}
}
My output was ok
Output :
run:
[[(1.346389790047983, 0.16747833178910174), (0.8336162865533764, 1.070466414773145), (-0.16747833178910165, 1.346389790047983), (-1.070466414773145, 0.8336162865533764), (-1.346389790047983, -0.16747833178910157), (-0.8336162865533766, -1.070466414773145), (0.1674783317891015, -1.346389790047983), (1.070466414773145, -0.8336162865533766)]]
BUILD SUCCESSFUL (total time: 0 seconds)
But I want this in a array or list of x+iy format . I have tried both complexFormat.Parse() and complexFormat.format() on each list item , but that case generates exception.
Would you please explain better way to do this?
You need to use the ComplexFormat as follows, calling the format() method on a single number of type Complex each time:
formatter = new ComplexFormat();
for (Complex c : list2)
{
System.out.println(formatter.format(c));
}
This code should replace your current line System.out.println(Arrays.toString(list2.toArray())); and you'll be good to go...
but...
you probably don't need the hassle of creating and using list2, just set up list as a List<Complex> rather than List<Object> and use that directly. So a final version of cut down code could be :
package complex;
import java.util.List;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.complex.ComplexFormat;
public class Do
{
public static void main(String[] args)
{
ComplexFormat complexFormat = new ComplexFormat();
Complex r = new Complex(6.3,9.6);
List<Complex> list = r.nthRoot(8);
for (Complex c : list)
{
System.out.println(complexFormat.format(c));
}
}
}
Output
1.34638979 + 0.1674783318i
0.8336162866 + 1.0704664148i
-0.1674783318 + 1.34638979i
-1.0704664148 + 0.8336162866i
-1.34638979 - 0.1674783318i
-0.8336162866 - 1.0704664148i
0.1674783318 - 1.34638979i
1.0704664148 - 0.8336162866i
Note - the documentation for ComplexFormat is here and, in particular, you should notice that if you instantiate it with no arguments (as I do above), it defaults to the x + yi format. If you want to play with the format, you pass parameters when you instantiate the formatter, as covered in those docs.
I'm trying to create some kind of list to store values from the array 'table'. (I'm using a arraylist here, but should I be using a list instead?) However, every time I try to compile, it throws the following error:
cannot find symbol
symbol : class ArrayList
location: class players.TablePlayer
The code is below.
public class TablePlayer extends Player {
int[][] table;
ArrayList goodMoves;
public TablePlayer(String name) {
super(name);
}
#Override
public int move() {
int oppLast = opponentLastMove();
int myLast = myLastMove();
if (!isLegalMove(oppLast)) {
return 0; // temporary
}
if (wonLast()) {
table[oppLast][myLast] = 1;
table[myLast][oppLast] = -1;
}
if ((wonLast() == false) && (oppLast != myLast)) {
table[oppLast][myLast] = -1;
table[myLast][oppLast] = 1;
}
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table.length; j++) {
if (table[i][j] == 1) {
goodMoves.add(table[i][j]);
}
}
}
return oppLast; // temporary
}
#Override
public void start() {
int[][] table = new int[7][7];
ArrayList<int> goodMoves = new ArrayList<int>();
}
}
Any help would be great, thanks!
Do you have an import statement in the top of the file?
import java.util.ArrayList;
While doing any java program just
import java.util.*;
Because * will import all the packages from util.
And all the basic package are present in that java.util like Scanner, ArrayList, etc...
So to avoid errors first check you have imported that.
Before use a class, you need to import it into you class file definition.
Add it on top of your file:
import java.util.ArrayList;
For more info about imports, look it up here
It is recommended to learn how to use a IDE, like Eclipse, Netbeans. It will help you with these common mistakes when we are programming in Java (in this case) outside a integrated environment.
I am new to the community and on a path of learning now.
But I think the main problem is of int
Wrong
ArrayList <int> goodMoves = new ArrayList <int>();
Right
ArrayList <Integer> goodMoves = new ArrayList <Integer>();