Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Loezi
Dec 18, 2012

Never buy the cheap stuff

DholmbladRU posted:

Questions about Map.

The Java interface Map (and all classes that implement it) is sort of like a collection of Entries. An Entry is an object that contains a Key and a Value. So Map is a collection of Key-Value pairs. The order of these entries in the map depends on the algorithm used in the actual implementation. A TreeMap is always sorted while something like HashMap makes no quarantees about the order.

So at this points Map seems like it's essentially a Collection<Entry<Key, Value>> but there's more to it. A map guarantees that any value of Key only exists a maximum of one time in the Map, but at the same time allows for more than one instance of one Value object in the same Map. Two different instances of class Key are considered to be the same if key1.equals(key2), even if key1 and key2 are different objects.

Another way that map differs from Collection<Entry<Key, Value>> is that you have multiple ways of iterating over it. You can retrieve all the keys as a Set<Key>, all the values as a Collection<Value> or all the entries as Set<Entry<Key, Value>>.

You can also ask the map directly for whether it contains a specific Key or Value.

This is one of the really good sides of maps: they are really good at determining whether a specific Key exists in the map or not. When you ask an ArrayList<Value> if a certain value exists in it, it needs to go over the whole list before determining "nope, not here". This can take a really long time if you have a huge list. Meanwhile something like a HashMap can just say the same thing -- with some algorithmic magic -- in the same rather fast time no matter the size of the map (Hash collisions are a thing but we'll skip those here). TreeMap is also quicker than the ArrayList but trades some speed for being in a specific, guaranteed order.

That in a nutshell is the Map interface. As for initializing a map and values:

You can always add new stuff to the Map. There is no point after which the map is "set in stone" and unchangeable. When adding an Entry. iIf there already exists an Entry with the same Key as your new Entry, the previous Entry is overwritten. Some maps (HashMap, f.ex.) consider null to be legit as both Key and Value. So you could just put("Whatever", null) as a placeholder but I'd say that seldom a useful thing.

As for the relation to PHP's associative arrays , I don't really speak PHP but after a quick glance at the PHP docs I'd say it's something like this:

Java's map can contain anything as a Key and is not always sorted. Java has multiple implementations of Map, each with its own upsides and downsides. Understanding these requires understanding Big O notation but here'sa thing you can look at if you are familiar with it.

Adbot
ADBOT LOVES YOU

Lord Windy
Mar 26, 2010
I've got a hypothetical that I don't know how to test but do want an answer for.

If there is an object method that has a synchronization lock on it, and there are threads in queue with different priority levels (say first in line is a priority level 5, second in line is priority 3 and third is priority 10) how does Java work out who goes first? If it a first in first out or will it let the highest priority thread in front?

I ideally want the top priority thread to get in first as I don't want to let it wait if the queue is long. But information I find can't tell me one way or the other.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Lord Windy posted:

I've got a hypothetical that I don't know how to test but do want an answer for.

If there is an object method that has a synchronization lock on it, and there are threads in queue with different priority levels (say first in line is a priority level 5, second in line is priority 3 and third is priority 10) how does Java work out who goes first? If it a first in first out or will it let the highest priority thread in front?

I ideally want the top priority thread to get in first as I don't want to let it wait if the queue is long. But information I find can't tell me one way or the other.

The answer is neither. If multiple threads are waiting on the same concurrency object, it's unspecified which thread will acquire it when it becomes available. You can also make a particular concurrency object "fair", which makes it a strict FIFO order, at the cost of some throughput.

Lord Windy
Mar 26, 2010

Jabor posted:

The answer is neither. If multiple threads are waiting on the same concurrency object, it's unspecified which thread will acquire it when it becomes available. You can also make a particular concurrency object "fair", which makes it a strict FIFO order, at the cost of some throughput.

Well, maybe I can ask the thread for a 'best practice'. I've got two methods, one is use by threads as a callback function in regards to sockets. A second method is a polling method by the main thread that collects all the data that the other threads are depositing at set intervals (every 100ms).

code:
    public void recieveInformation(Sentence toAdd){
        synchronized (lock1){
            RawInputs.add(toAdd);
        }
    }

    private void gatherInformation(){
        synchronized (lock1){
            Inputs = RawInputs;
            RawInputs = new ArrayList<Sentence>();
        }
    }
To me this makes perfect sense, the main thread is priority 10 and everything else is 5. Main thread just waltzes into the front of the queue. But if this is the wrong way let me know and I'll fix it. I'm not experiencing any deadlock yet, but at the same time I am not really testing it.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Is it important that the main thread gets the lock immediately when it asks instead of waiting for a couple of other threads to take their turn first? If so, why?

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
This is probably a good chance to explore Java's lock classes rather than using synchronized.

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/package-summary.html

Lord Windy
Mar 26, 2010

Jabor posted:

Is it important that the main thread gets the lock immediately when it asks instead of waiting for a couple of other threads to take their turn first? If so, why?

I'm probably pre-optimising to be honest. I'm working on some examples from a MUD programming book and I'm anxious that I don't gently caress the sockets up because I'm not doing it's version of sockets (it was written back in 2003 and is a little out of date).

Brain Candy
May 18, 2006


Put whatever you receive into a BlockingQueue, take crap out with drainTo. This does what you want effectively without changing priority for all locks that you might touch.

ROFLburger
Jan 12, 2006

This is a stupid question. I'm using java.util.logging and I feel like I'm doing something wrong. Does there exist a logging API where I don't have to create a new logger, level, and handlers in every class that I want to be able log from? It seems wrong to keep copy pasting this in all of my classes(that I want to log from) where the only difference is changing the filename to "classname.log". I'm wondering if theres a better way than jamming all of the logger setup poo poo into the constructor of each class?

TheresaJayne
Jul 1, 2011

ROFLburger posted:

This is a stupid question. I'm using java.util.logging and I feel like I'm doing something wrong. Does there exist a logging API where I don't have to create a new logger, level, and handlers in every class that I want to be able log from? It seems wrong to keep copy pasting this in all of my classes(that I want to log from) where the only difference is changing the filename to "classname.log". I'm wondering if theres a better way than jamming all of the logger setup poo poo into the constructor of each class?

Look at SLF4J and LOG4J

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe
Those don't solve the problem of setting up the logger in each class. What you want is Lombok
http://projectlombok.org/features/Log.html

Brain Candy
May 18, 2006

Janitor Prime posted:

Those don't solve the problem of setting up the logger in each class. What you want is Lombok
http://projectlombok.org/features/Log.html

This is swatting a fly with a sledgehammer.

ROFLburger posted:

This is a stupid question. I'm using java.util.logging and I feel like I'm doing something wrong. Does there exist a logging API where I don't have to create a new logger, level, and handlers in every class that I want to be able log from? It seems wrong to keep copy pasting this in all of my classes(that I want to log from) where the only difference is changing the filename to "classname.log". I'm wondering if theres a better way than jamming all of the logger setup poo poo into the constructor of each class?

Use SLF4J so you don't care what the logging backend is, if that's an option. You shouldn't be making levels and handlers in every class.

Set up a macro in your IDE of choice so when you type logger your IDE does the thing for you.

Googling logger macro <IDE> found

http://stackoverflow.com/questions/6097646/intellij-live-template
http://stackoverflow.com/questions/1028858/useful-eclipse-java-code-templates

Volguus
Mar 3, 2009

Brain Candy posted:

This is swatting a fly with a sledgehammer.


Use SLF4J so you don't care what the logging backend is, if that's an option. You shouldn't be making levels and handlers in every class.

Set up a macro in your IDE of choice so when you type logger your IDE does the thing for you.

Googling logger macro <IDE> found

http://stackoverflow.com/questions/6097646/intellij-live-template
http://stackoverflow.com/questions/1028858/useful-eclipse-java-code-templates

Now I saw his statement about "levels and handlers in every class". What is that and where does it come from?
The only thing that one has to do in a class is to declare the log variable (probably static final) and then use it. Which the @Log annotation does for you. It's one line, nothing more, nothing less. The annotation itself will take one line as well (yes, i know they can be put on the same line, besides the point).
Anyway, the logging framework used is irrelevant, even if the question was about that. The question itself was wrong. None of them are any more complicated than the other. The differences are so minor that essentially you can roll the dice. Using slf4j or log4j or logback itself or common-logging: same thing, different name.

Doing more work in a constructor than it is needed ... that's relevant and most likely unnecessary. ROFLburger, please post some code, I'm really curious as to what in the world are you doing there. Why do you have more than one line of code for declaring the log variable in a class?

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe
JUL allows you to create instance variables for the log levels that you pass in by doing logger.log(Level level, String msg) instead of using the shorthand logger.info(String msg) or logger.warn(String msg)


Brain Candy posted:

This is swatting a fly with a sledgehammer.

I don't think it's that heavy handed, i's just a compile time annotation not a lib you have to ship with your code. Also the main advantage of the annotation is that it saves you from copy and paste errors that leave the name of the previous class instead of the new one. I've had this happen to us a couple of times and it slipped by code review.

Janitor Prime fucked around with this message at 19:53 on Feb 20, 2015

geeves
Sep 16, 2004

Have a Jersey 2 question that I hope is just something small that I'm missing. We're creating an Asset library for users to upload video, docs, etc. for the projectson which they'll be working. I've found similar answers, but those cover most of what I've already done, with the form, method, web.xml and registering MultiPartFeature.class. Here the simple act of implementing a ContainerRequestFilter impedes MULTIPART_FORM_DATA (file upload) from uploading. Returning 415. I'm curious what I'm missing, as I've followed the docs.

Anyway, the following works sans filter and the file uploads as expected and returns what is expected.

code:
public class AssetController extends BaseController {  //Base implements ResourceConfig
    
    public AssetController() {
        super();  // calls super(MultiPartFeature.class);
    }

    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    public Response uploadAsset(@FormDataParam("file") InputStream uploadedInputStream,
                                @FormDataParam("file") FormDataContentDisposition fileDetail,
                                @Context HttpServletRequest request)
When I attempt to add a Filter - every post, put, delete, etc. continues to work except for Uploading a file with form data- if I remove the @Provider annotation (disabling it), the upload again works. The filter method below is completely blank at the moment, but I'm hoping to use it for some simple permissions authentication

code:
@Provider
public class AuthorizationRequestFilter implements ContainerRequestFilter {

    @Context
    private HttpServletRequest request;

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // this code is currently empty and just writing to logs the header properties, etc.
web.xml just in case:
code:
<servlet>
        <servlet-name>Rest</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>foo.rest</param-value>
        </init-param>
        <init-param>
            <param-name>org.codehaus.jackson.jaxrs</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>org.glassfish.jersey.filter.LoggingFilter;org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
Edit: I found the issue, it was looping thorugh some headers and I left in Iterator.remove() which was deleting them causing it not to accept the file :downs:

geeves fucked around with this message at 21:43 on Feb 20, 2015

Brain Candy
May 18, 2006

Janitor Prime posted:

I don't think it's that heavy handed, i's just a compile time annotation not a lib you have to ship with your code. Also the main advantage of the annotation is that it saves you from copy and paste errors that leave the name of the previous class instead of the new one. I've had this happen to us a couple of times and it slipped by code review.

It's not just a compile time annotation, it's a pre-processor instruction. The code you write with Lombok is not Java. That's not a ding on it's quality, but it effects your entire tool-chain.

Volguus
Mar 3, 2009

Brain Candy posted:

It's not just a compile time annotation, it's a pre-processor instruction. The code you write with Lombok is not Java. That's not a ding on it's quality, but it effects your entire tool-chain.

I don't think that Java works this way. At all... The C/C++ thread is just around the corner. This lombok code is very much java. As java as you're gonna get anywhere.

lamentable dustman
Apr 13, 2007

🏆🏆🏆

Janitor Prime posted:

Also the main advantage of the annotation is that it saves you from copy and paste errors that leave the name of the previous class instead of the new one. I've had this happen to us a couple of times and it slipped by code review.

This is happened to my projects more then I care to admit...

Brain Candy
May 18, 2006

Volguus posted:

I don't think that Java works this way. At all... The C/C++ thread is just around the corner. This lombok code is very much java. As java as you're gonna get anywhere.

:allears:

Please show me a compliant Java compiler that can compile an example taken from the link Janitor Prime provided:

code:
public void example2() {
    val map = new HashMap<Integer, String>();
    map.put(0, "zero");
    map.put(5, "five");
    for (val entry : map.entrySet()) {
       System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
    }
 }

The Laplace Demon
Jul 23, 2009

"Oh dear! Oh dear! Heisenberg is a douche!"

Volguus posted:

I don't think that Java works this way. At all... The C/C++ thread is just around the corner. This lombok code is very much java. As java as you're gonna get anywhere.

Lombok isn't vanilla Java. Annotations just aren't powerful enough to do this sort of thing. If you're ever curious, Lombok comes with a tool called delombok that emits the postprocessed Java code.

README posted:

Project Lombok makes java a spicier language by adding 'handlers' that know how to build and compile simple, boilerplate-free, not-quite-java code.

ROFLburger
Jan 12, 2006

So here's a small example of what I was talking about with java.util.logger http://pastebin.com/N3FsXypz I guess it's not terrible, but it just feels wrong to have each that contains a logger be required to build out the handlers and formatters and whatever else.

I checked out log4j Like you guys suggested and it's exactly what I was looking for. Setting up the logging environment from the log4j.properties file and adding one single line to each class seems a lot easier

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

ROFLburger posted:

So here's a small example of what I was talking about with java.util.logger http://pastebin.com/N3FsXypz I guess it's not terrible, but it just feels wrong to have each that contains a logger be required to build out the handlers and formatters and whatever else.

That's because you're doing it wrong.

The right way to do log configuration is to set it up in the LogManager, so that individual classes will get that configuration by default when they call getLogger(). This also means that should you need to change your logging configuration (for example, you want to turn off logs below a particular severity for release builds), that only needs to be done in one place instead of everywhere that does logging.

ROFLburger
Jan 12, 2006

Jabor posted:

That's because you're doing it wrong.

The right way to do log configuration is to set it up in the LogManager, so that individual classes will get that configuration by default when they call getLogger(). This also means that should you need to change your logging configuration (for example, you want to turn off logs below a particular severity for release builds), that only needs to be done in one place instead of everywhere that does logging.

Using Log4j, I can create and configure individual loggers using the log4j properties file, without having to manually do any filehandler or formatter instantiation. Is that also possible using the LogManager or its configuration file? It's not immediately clear to me after a cursory google and I didn't see any thing like that in the examples that I found the other day.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

ROFLburger posted:

Using Log4j, I can create and configure individual loggers using the log4j properties file, without having to manually do any filehandler or formatter instantiation. Is that also possible using the LogManager or its configuration file? It's not immediately clear to me after a cursory google and I didn't see any thing like that in the examples that I found the other day.

The real answer is "don't gently caress with any of that, just call getLogger() and use it as-is". That way the environment in which your application is running can configure the logging appropriately. If you go around in your code telling something to only log to one particular file, whoever ends up having to debug your code is going to be really annoyed that they can't just dump it straight into their logs analyzer. How something should be logged is defined by the execution environment, not the code itself.

When running a jar, the LogManager by default uses the configuration in the JRE directory. You can specify a custom configuration file using a flag to the JRE. (All this information is in the LogManager javadoc, incidentally). The default configuration file in your JRE directory is a pretty good example of how to write one.

Volguus
Mar 3, 2009

Brain Candy posted:

:allears:

Please show me a compliant Java compiler that can compile an example taken from the link Janitor Prime provided:

code:
public void example2() {
    val map = new HashMap<Integer, String>();
    map.put(0, "zero");
    map.put(5, "five");
    for (val entry : map.entrySet()) {
       System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
    }
 }

Any java compliant compiler can compile that code+the code generated by delombok. However, that is not a pre-processor instruction, since java does not have such a thing. That is simply code generation+injection. You don't have things like #ifdef or #define in Java. Same with the @Log annotation. It just injects a field "public static final ... log" in the binary.

foonykins
Jun 15, 2010

stop with the small talk


I'm having one hell of a time wrestling with this recursive algorithm for my class. In short, it's supposed to solve any "summation puzzle" for k amount of characters using multiple recursion. The pseudocode I'm supposed to be following is:



I'm using linked lists to house the used and unused characters. I'm pretty confident I have the concept down, but for some reason I can't seem to get the recursive call to work. Here's my code for the algorithm. If you want me to post the code for my main class I'll be happy to.

code:

public static void PuzzleSolve(int k, LinkedList s , LinkedList u)
   {
       for(int i=0; i<k-1; i++)
       {
           s.addLast(u.getFirst());
           u.removeFirst();
           System.out.println(s.toString());
           if (k==1)
                {
                    if (u.size()==0)
                    {
                        System.out.println(s.toString());
                    }
                    
                }
           else
                    {
                        PuzzleSolve(k-1, s, u);
                        u.addFirst(s.removeLast());
                    }
       }

I have a feeling I'm missing something entirely obvious, I just can't put my finger on it. Am I taking the pseudocode too literally? Does this need to be a lot more complex than I have it right now?

edit:fix stupid grammar coming from my stupid pre-coffee brain

foonykins fucked around with this message at 15:37 on Feb 21, 2015

The Laplace Demon
Jul 23, 2009

"Oh dear! Oh dear! Heisenberg is a douche!"

Volguus posted:

Any java compliant compiler can compile that code+the code generated by delombok. However, that is not a pre-processor instruction, since java does not have such a thing. That is simply code generation+injection. You don't have things like #ifdef or #define in Java. Same with the @Log annotation. It just injects a field "public static final ... log" in the binary.

Not the most recent of posts, but Project Lombok uses internal javac & ecj APIs because the annotation processing API isn't powerful enough. The standard itself as specified in JSR 269 doesn't support code generation. Check out the javax.annotation.processing packages, there's nothing there supporting code generation during build.

A compiler being standards compliant has nothing to do with whether or not it can compile code using Lombok. It has to expose an internal API allowing Lombok to modify the AST during annotation processing, and somebody needs to write a handler for it in Lombok.

Lombok's a preprocessing step. Annotation processors are run, and then the code is compiled to bytecode. The processors are run before code compilation. Lombok is a preprocessor.

The Laplace Demon fucked around with this message at 16:14 on Feb 21, 2015

Kilson
Jan 16, 2003

I EAT LITTLE CHILDREN FOR BREAKFAST !!11!!1!!!!111!

foonykins posted:

I'm having one hell of a time wrestling with this recursive algorithm for my class. In short, it's supposed to solve any "summation puzzle" for k amount of characters using multiple recursion. The pseudocode I'm supposed to be following is:



I'm using linked lists to house the used and unused characters. I'm pretty confident I have the concept down, but for some reason I can't seem to get the recursive call to work. Here's my code for the algorithm. If you want me to post the code for my main class I'll be happy to.

code:
public static void PuzzleSolve(int k, LinkedList s , LinkedList u)
   {
       for(int i=0; i<k-1; i++)
       {
       }

I have a feeling I'm missing something entirely obvious, I just can't put my finger on it. Am I taking the pseudocode too literally? Does this need to be a lot more complex than I have it right now?

edit:fix stupid grammar coming from my stupid pre-coffee brain

Nowhere in the pseudocode is it looping over k like that. That's what the recursive call is for, so that you don't have to do this loop. You have to loop over the elements of u instead.

Also, your very last statement (add e back to u) is in the wrong place.

The Laplace Demon
Jul 23, 2009

"Oh dear! Oh dear! Heisenberg is a douche!"

foonykins posted:

I'm having one hell of a time wrestling with this recursive algorithm for my class. In short, it's supposed to solve any "summation puzzle" for k amount of characters using multiple recursion. The pseudocode I'm supposed to be following is:



I'm using linked lists to house the used and unused characters. I'm pretty confident I have the concept down, but for some reason I can't seem to get the recursive call to work. Here's my code for the algorithm. If you want me to post the code for my main class I'll be happy to.

code:

public static void PuzzleSolve(int k, LinkedList s , LinkedList u)
   {
       for(int i=0; i<k-1; i++)
       {

I have a feeling I'm missing something entirely obvious, I just can't put my finger on it. Am I taking the pseudocode too literally? Does this need to be a lot more complex than I have it right now?

edit:fix stupid grammar coming from my stupid pre-coffee brain

You're not taking the pseudocode literally enough in some respects. What's that outer loop supposed to do, anyways? Why are you using LinkedLists? What are they supposed to contain? Integers? Your compiler should be yelling at you for using raw types (LinkedList vs. LinkedList<Integer>).

Here's the basic skeleton of your function, sans the implementation:
code:
public List<List<Integer>> puzzleSolve(int k, List<Integer> s, Set<Integer> u) {
  List<List<Integer>> solutions = new ArrayList<>();
  // pseudocode implementation goes here
  return solutions;
}
And here's some building blocks:
code:
// to iterate over the elements of a collection
for (Integer e : u) {
  // loop body goes here
}

// to add an element to the end of a List: [url]http://lmgtfy.com/?q=list+java&l=1[/url]
s.add(e);

// to remove an element from a Set: [url]http://lmgtfy.com/?q=set+java&l=1[/url]
u.remove(e);

// to make a shallow copy of a list (or any collection) (you'll need this a lot...)
List<Integer> copy = new ArrayList<>(s);

// to add a list of elements to a list: [url]http://lmgtfy.com/?q=list+java&l=1[/url]
solutions.addAll(otherSolutions);

// to remove the last element from a list: [url]http://lmgtfy.com/?q=list+java&l=1[/url]
s.remove(s.size() - 1);

// to add an element to a set: [url]http://lmgtfy.com/?q=set+java&l=1[/url]
u.add(e);
A couple gotchas you'll probably hit:
  • Don't modify the collection you're iterating over, ever. Make a shallow copy of it first.
  • Similarly, don't add s to your solutions. Add a shallow copy of it. You're modifying s, it'll change next loop iteration.

Learn to look up and read documentation. It's one of the most useful skills you'll ever learn in programming.

Oh, and a personal nitpick: LinkedLists are almost always terrible in practice. Don't use them unless you've benchmarked things and actually measured a performance improvement. Your default should be ArrayLists.

foonykins
Jun 15, 2010

stop with the small talk


Kilson & The Laplace Demon posted:

A whole bunch of useful :words:

Thanks to both of you for the feedback. I came back to college after a year and change, and getting thrown back into an advanced data structures course is a bit of a sobering situation. I'm glad you guys are feeding me tid bits of information instead of just doing it for me, it's helping me get my groove back immensely.

Anywho...

I did what Kilson said and got rid of that extraneous for loop, and did part of what Lapdance said and made soft copies of my collections (I plan on implementing the rest of your suggestions once I get this drat recursive call working properly). Here's where I'm at so far:

code:
public static void PuzzleSolve(int k, LinkedList s , LinkedList u)
   {
       LinkedList used = s;
       LinkedList unused = u;
       while(u.isEmpty() == false)
       {
  
            used.addLast(unused.getFirst());
            unused.removeFirst();
            System.out.println("used" + used.toString());
            System.out.println("Unused" + unused.toString());
            if (k==1)
            {
                System.out.println("solution!");
                System.out.println(used.toString());
            }
            else
            {
                System.out.println("next");
                unused.addLast(used.removeFirst());
                PuzzleSolve(k-1, used, unused);
            }
           
       }
   }
I'm definitely one step closer, as the recursive call is happening, except it's not moving forward after every character. Here's my output:

code:
possible combinations of a, b and c:
used[a]
Unused[b, c]
next
used[b]
Unused[c, a]
next
used[c]
Unused[a, b]
solution!
[c]
used[c, a]
Unused[b]
solution!
[c, a]
used[c, a, b]
Unused[]
solution!
[c, a, b]
Elapsed time = 2.0milliseconds
As you can see, it's iterating over every character once, and once it hits the last character (c in this case) it almost starts to do what I need it to. I'm trying to accomplish a nice, neat little tree like this:



I have a feeling that either my base case is wrong, or I'm calling on the method in the wrong spot. I'm sorry if I'm making GBS threads up the thread, and I'll stop and move my questions elsewhere if need be.

Kilson
Jan 16, 2003

I EAT LITTLE CHILDREN FOR BREAKFAST !!11!!1!!!!111!
It seems like you're still missing the last couple statements from the pseudocode. I think your recursive call is working fine, but at each step your list is getting smaller instead of just being a new permutation, because of those missing statements that add the element back to the list of unused elements.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

foonykins posted:

Thanks to both of you for the feedback. I came back to college after a year and change, and getting thrown back into an advanced data structures course is a bit of a sobering situation. I'm glad you guys are feeding me tid bits of information instead of just doing it for me, it's helping me get my groove back immensely.

Anywho...

I did what Kilson said and got rid of that extraneous for loop, and did part of what Lapdance said and made soft copies of my collections (I plan on implementing the rest of your suggestions once I get this drat recursive call working properly). Here's where I'm at so far:

code:
public static void PuzzleSolve(int k, LinkedList s , LinkedList u)
   {
       LinkedList used = s;
       LinkedList unused = u;
       while(u.isEmpty() == false)
       {
  
            used.addLast(unused.getFirst());
            unused.removeFirst();
            System.out.println("used" + used.toString());
            System.out.println("Unused" + unused.toString());
            if (k==1)
            {
                System.out.println("solution!");
                System.out.println(used.toString());
            }
            else
            {
                System.out.println("next");
                unused.addLast(used.removeFirst());
                PuzzleSolve(k-1, used, unused);
            }
           
       }
   }
I'm definitely one step closer, as the recursive call is happening, except it's not moving forward after every character. Here's my output:

code:
possible combinations of a, b and c:
used[a]
Unused[b, c]
next
used[b]
Unused[c, a]
next
used[c]
Unused[a, b]
solution!
[c]
used[c, a]
Unused[b]
solution!
[c, a]
used[c, a, b]
Unused[]
solution!
[c, a, b]
Elapsed time = 2.0milliseconds
As you can see, it's iterating over every character once, and once it hits the last character (c in this case) it almost starts to do what I need it to. I'm trying to accomplish a nice, neat little tree like this:



I have a feeling that either my base case is wrong, or I'm calling on the method in the wrong spot. I'm sorry if I'm making GBS threads up the thread, and I'll stop and move my questions elsewhere if need be.

Here's what your code's doing:
k=3, used=[ ], unused=[a, b, c]
// remove first element in unused, add as the last element in used
k=3, used=[a], unused=[b, c]
// check if k==1, otherwise:
// remove first element from used, add as the last element in unused
k=3, used=[ ], unused=[b, c, a]
// call the method again with these parameters, except k is one less


So what your code is actually doing is taking an empty s, a sequence of elements u, rotating the elements in u so the first element is now at the back, and calling the method again - s is still empty, u has been rearranged, k is one step closer to giving up. Eventually it hits 1 and prints whatever happened to be at the front of u when it was passed in that time around.

You need to make sure that when you recursively call the method again, you're passing in the work you've done, so the next recursion can work on that result. In this case, you need to be adding something to s and removing it from u, so the next recursion can add more to s and remove more from u.

Are you using an IDE? A debugger will help you a ton, you can step through bit by bit and watch the value of the variables, and you'll see when things go weird and you'll be able to track the problem down immediately. If you aren't using one, it might help to print all your variables before you pass them into the method (or when the method receives them), so you can check it's getting the state you'd expect at each step

foonykins
Jun 15, 2010

stop with the small talk


baka kaba posted:

You need to make sure that when you recursively call the method again, you're passing in the work you've done, so the next recursion can work on that result.

This is precisely where I'm hung up. Would another set of copies solve this issue? Would it, in sorts, work a kind of save-state when the method is called again?

Also, in terms of IDEs, im using NetBeans. I've never worked with a debugger before. I've heard great things about IntelliJ Idea but was having a hard time configuring it on my Mac. All that talk is for the IDE thread though.

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

foonykins posted:

This is precisely where I'm hung up. Would another set of copies solve this issue? Would it, in sorts, work a kind of save-state when the method is called again?

Also, in terms of IDEs, im using NetBeans. I've never worked with a debugger before. I've heard great things about IntelliJ Idea but was having a hard time configuring it on my Mac. All that talk is for the IDE thread though.

Oh man, I couldn't imagine doing any sort of even slightly complex programming without a step by step debugger. As a tutor it's the first thing I would tell people to try when they were having issues getting something working, so excuse me if I evangelize a little bit :v:. Here's how to use the one in Netbeans:



Click the left gutter next to the line you want the debugger to pause on. Execution will stop just before that line begins to execute, so you want one just before the piece of code you're interested in tracing around. You can also create a bunch of different kinds of breakpoints from the Debug > New Breakpoint... menu item. You can have breakpoints on as many lines as you want, and as you'll see, you can resume execution after it pauses at one breakpoint and let it pause at the next.



Next, click the icon that should be on the right of Run, which is Debug.

Your program will run until it hits your breakpoint, then the interface will change around a bit to show you the debugger, and the line will turn green. Now, your program is paused. On the left, the debugger tab shows the current call stack, so you can see what methods have called what methods in your program. In this screenshot, main() called getNth() on line 10 of class Lab7. At the bottom, the variables tab shows instance and local variables that are defined/in scope for the current line of code being executed. The disclosure triangle lets you peek into the memory of objects, so for instance my little LinkedList has its own first, last, and count variables, and I can drill down through references to see what everything is set to.

Once execution has paused, there are a few ways you can progress: step into, step over, step out, and continue (there are others in Netbeans, but those four are found pretty much in every IDE I've used.) Step into means move to the next line, and if the instruction pointer moves into another method, follow it. You'll use it when you're interested in how the method being called works. If you aren't, and just want it to run, you can step over, which is similar to step into, except if a method is called on that line, the entire method (including all calls that method makes) and execution will pause when that method returns. Step out is useful when you're done with the current method you're in, and want to skip to the point when that method returns. Continue will resume execution normally, stopping at the next breakpoint if it encounters one (this includes hitting the same breakpoint again.)

This is a basic overview of how to use the debugger. There are quite a few advanced features that you may want to look into later, but that should be good for what you're doing now. The key is to determine what you are interested in watching, both in terms of code flow and how variables change in response to your code, and then keeping track as you step through line by line. It'll reveal areas where what you assume it's doing and what it actually does differ, and can help show errors in logic. It only gets more useful as software gets more complex; I work on a very very large Java EE product, and I depend on the debugger quite a bit.

foonykins
Jun 15, 2010

stop with the small talk


carry on then posted:

crazy useful debugger knowledge

Holy poo poo was that fruitful information! Thanks so much for that, this should really help me figure out what the hell is going on. I'm still currently stuck on elements circling back and forth between the used and unused containers, except now it's stuck in an infinite loop. For some reason k isn't incrementing down past 1. It's the same loop i was in before, where the first element of unused gets placed into used then circled back around as the last element of unused again.

code:
public static void PuzzleSolve(int k, LinkedList s , LinkedList u)
   {
       LinkedList used = s;
       LinkedList unused = u;
       while(u.isEmpty() == false)
       {
  
            used.addLast(unused.getFirst());
            unused.removeFirst();
            System.out.println("used" + used.toString());
            System.out.println("Unused" + unused.toString());
            if (k==0)
            {
                if(used.size() == 0)
                    return;
                System.out.println("solution!");
                System.out.println(used.toString());
                System.out.println("k =" + k);
            }
            else
            {
                System.out.println("next");
                LinkedList saveUsed = used;
                LinkedList saveUnused = unused;
                System.out.println("k =" + k);
                PuzzleSolve(k-1, saveUsed, saveUnused);
                unused.addLast(used.remove());
                
            }
           
       }

Output:
code:
run:
possible combinations of a, b and c:
used[a]
Unused[b, c]
next
k =3
used[a, b]
Unused[c]
next
k =2
used[a, b, c]
Unused[]
next
k =1
used[b, c, a]
Unused[]
next
k =1
used[c, a, b]
Unused[]
next
k =1
used[a, b, c]
Unused[]
next
k =1
//repeat ad nauseum
I've been loving around with different base cases, and putting the call in different spots, although I know now that isn't my problem. I've been pounding away at this at work since 8AM though, so I'm putting it down for the night and heading to the bar (babycastles in NYC if you want to stop by and tell me how bad of a coder I am) so I can have a fresh head tomorrow.

The Laplace Demon
Jul 23, 2009

"Oh dear! Oh dear! Heisenberg is a douche!"

Java code:
LinkedList used = s;
In Java, this makes used and s the _same_ object, not copies. To repeat, this doesn't make a copy. Modifications to s happen to used too, because they are the same LinkedList.

Java code:
while(u.isEmpty() == false) {
  // stuff
}
This loops forever as long as u isn't empty. This is not the same loop condition as the pseudocode. The pseudocode iterates over every element in u.

Reread through my last post, toss out everything you have right now, and do exactly what the pseudocode says. It looks like you're just moving things around hoping it does what you want and that just isn't going to work. Post what you have after trying that.

Volguus
Mar 3, 2009

The Laplace Demon posted:

....
Lombok's a preprocessing step. Annotation processors are run, and then the code is compiled to bytecode. The processors are run before code compilation. Lombok is a preprocessor.

Bolding things won't make them true. Lombok does indeed change the AST, as it does change the bytecode itself when it needs to. If it makes you feel better, sure, call it a preprocessor. However, java as a language, as a toolkit, as an SDK, does not support preprocessor instructions/declarations.
There are tools/libraries out there (cglib for example, lombok itself, ow2 asm) that do allow one to mess with with the AST or the bytecode itself (ORMs for example make heavy usage of this). That does not make them "pre-processors".

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Volguus posted:

Bolding things won't make them true. Lombok does indeed change the AST, as it does change the bytecode itself when it needs to. If it makes you feel better, sure, call it a preprocessor. However, java as a language, as a toolkit, as an SDK, does not support preprocessor instructions/declarations.

Lombok-java isn't standard Java. You could have a standards-compliant Java implementation that will completely choke on a Lombok-java project. You explicitly need to use the preprocessor to turn it into standard Java if you want to compile it with something that Lombok doesn't have compiler-specific hacks for to make it work.

This isn't true of all annotation processors. Annotations and annotation processors are part of the standard, and if you write an annotation processor that restricts itself to things supported by the standard instead of just digging into javac internals to gently caress with the AST, it's totally fair to call that "normal Java". Lombok isn't one of those well-behaved, standards-conforming annotation processors though, so once you start using it, you're not using standard Java any more.

--

As an aside, "preprocessor" does not mean "something that looks for #commands in your source code and does things with them". A preprocessor is "something that processes your source before it is compiled". The C preprocessor is one example, but you're completely wrong if you claim that it's the only thing that meets the definition.

Jabor fucked around with this message at 04:21 on Feb 22, 2015

Kilson
Jan 16, 2003

I EAT LITTLE CHILDREN FOR BREAKFAST !!11!!1!!!!111!

The Laplace Demon posted:

Reread through my last post, toss out everything you have right now, and do exactly what the pseudocode says. It looks like you're just moving things around hoping it does what you want and that just isn't going to work. Post what you have after trying that.

This. That pseudocode is quite clear, so try to do exactly what it says. You've gotten a little closer, so that's good.

The Laplace Demon is correct that the main problem is that you need to copy the set 'u' before you iterate over it, then use the copy for all the logic. (Including in the recursive call.) As noted above, simply setting a new variable =u doesn't copy the data.

That's the only thing that differs even a tiny bit from the pseudocode.

There are two reasons to do that:

1) Java doesn't like if you modify a collection you're iterating over. It will throw exceptions.

2) You only want to use each element of 'u' once in the iteration, so if you keep adding stuff to u, it might not be clear where to stop iterating, because Java doesn't keep track of the state at the beginning of the iteration.

Adbot
ADBOT LOVES YOU

Volguus
Mar 3, 2009

Jabor posted:

As an aside, "preprocessor" does not mean "something that looks for #commands in your source code and does things with them". A preprocessor is "something that processes your source before it is compiled". The C preprocessor is one example, but you're completely wrong if you claim that it's the only thing that meets the definition.

And lombok doesn't process the source code, it processes the AST and the bytecode. The AST you get after the syntax analysis phase, and the bytecode after the actual compilation. The actual source code has been processed already, only after that lombok itself kicks in. This, therefore, does not meet your definition of a pre-processor.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply