• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Knute Snortum
  • Bear Bibeault
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Piet Souris
  • Ganesh Patekar
Bartenders:
  • Frits Walraven
  • Carey Brown
  • Tim Holloway

Boring, boring code duplication.

 
Ranch Hand
Posts: 152
2
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello dears,

Is there any way to avoid code repetition for this problem?
https://open.kattis.com/problems/tri

 
Bartender
Posts: 20841
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's not code duplication. You've got a reversed version basic calculator program there and each of those "duplicate" lines isn't a true duplicate. They merely form a pattern.

You also risk program failure, since you didn't allow for inputs that will attempt to divide by zero.

Some languages (not java) have macro meta-languages that can take the varying parts as arguments and generate those source lines automatically. For that matter, you could set up templates in many Java IDEs. But the final code will still end up looking like that at the source level.

Java does have a very powerful optimiser that may be able to crunch down some of that code internally and automatically make it run more efficiently, but from the source level you won't see it.
 
D.J. Quavern
Ranch Hand
Posts: 152
2
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, so there is no way to hold the arithmetic operators in an array or something similar?
 
Saloon Keeper
Posts: 10308
217
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can encapsulate each equation and its string representation in an object, and then loop through a collection of them:

I rewrote your equations so the operator is on the left hand side, and I eliminated

a = b + c and
a = b * c,

because those equations are equivalent to

a - b = c and
a / b = c.
 
Sheriff
Posts: 6030
157
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It seems the solution also needs to consider input like this:

5 15 3 -> 5=15/3

as well as

5 3 8 -> 5+3=8
 
Tim Holloway
Bartender
Posts: 20841
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:You can encapsulate each equation and its string representation in an object, and then loop through a collection of them:...



It's true. Inside every simple program is a complex program trying to get out.

D.J. Quavern wrote: Ok, so there is no way to hold the arithmetic operators in an array or something similar?



In a highly-interpreted language like Forth or Smalltalk, maybe. But in Java, arithmetic expressions are crunched down to bytecode sequences when the source program is compiled and not something you can alter freely at runtime (what the JVM can do with other languages than Java I won't address here).
 
D.J. Quavern
Ranch Hand
Posts: 152
2
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you everyone!

What does the arrow operator does?
 
Stephan van Hulst
Saloon Keeper
Posts: 10308
217
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's called a lambda expression. You may want to look it up in the tutorials.

Note however that my solution was a literal answer to your question, and in no way an endorsement that you should write programs this way. Tim is correct in that it's more complex than it needs to be.
 
Ranch Foreman
Posts: 3268
20
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Awww... I like Stephen's solution.  Mostly because it's along the same lines I though of. The question was how to eliminate the code duplication, after all.

This solution relies on existing classes, includes all 8 equation possibilities, and keeps the requested output order.  It also scales nicely for code complexity - if we add more operators, it's one line per operator.  If we add another argument order to check (like a+c=b) that's just one line.  And I think it's about as close as Java currently allows to what the OP was thinking about holding all the operators in an array - instead we map each operator symbol to a function that implements it:
 
Ranch Hand
Posts: 1168
11
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In the case of arguments 2, 2 and 4.  Should you get both 2+2=4 and 2*2=4 or just the addition equation?
 
Mike Simmons
Ranch Foreman
Posts: 3268
20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The OP gave a link to the problem statement: https://open.kattis.com/problems/tri

If there are multiple solutions, output any of them.



A previous version of my code had used LinkedHashMap to preserve the exact logic of the OP - but then I read that line and went with the nicer-looking Map.of().
 
Mike Simmons
Ranch Foreman
Posts: 3268
20
  • Likes 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Although there's another issue - would "Little Mirko" think that 5 / 2 = 2 is a valid solution?  Would his instructor agree?  I'm thinking that using integer division here isn't really correct, as far as the outside world is concerned.  Better to replace IntBinaryOperator with DoubleBinaryOperator, I think.

I expect some will balk at the idea of using doubles where equality is being tested, but I'm pretty sure it will be fine - if an integral solution exists, the double value will be equal to the int value.  Unless the ints are, what, 16 digits or more?  Close enough for government work.
 
Saloon Keeper
Posts: 3295
146
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I like Mike's solution, but here is one more of the same, using a TriPredicate. I must say, DJ's original solution is the easiest of all      
 
Mike Simmons
Ranch Foreman
Posts: 3268
20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nice.  And I agree, we're not really improving on the original.  But how else are we supposed to have fun?

Here's another alternative, much closer to the original:

All it really improves on is it gets rid of the multiple System.out.println() and the else ifs... but hey, that's duplication too. ;)
 
Bartender
Posts: 2293
95
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How about this:
It's almost the same as multiple print statements. But.. since we have a result, we can prepend, append, pass it on to screen in a label, print in console, etc...
 
D.J. Quavern
Ranch Hand
Posts: 152
2
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:I like Mike's solution, but here is one more of the same, using a TriPredicate. I must say, DJ's original solution is the easiest of all      


My solution is easiest of all, since I can't write anything classy with lambda expressions and streams and stuff ! Or a tripredicate!
 
Marshal
Posts: 64666
225
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did you write TriPredicate yourself? Please supply more details, even though we could probably work it our for ourselves if we actually used our brains
 
Piet Souris
Saloon Keeper
Posts: 3295
146
  • Likes 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My pleasure...

A "TriPredicate" is a type that I made up.

Suppose we have a function f of two variables, x and y, we can ask, for some three given values a, b, c, wether f(a, b) == c. Java 8+ has a type (interface) for such a function f, with two variables, and it is called a BiFunction. It is a generic type, a BiFunction<T, U, R> denotes a functon of two variables t and u, of type T and U respectively, and the result of that BiFunction is some value of type R.
If the two generic types involved are primitive ints, and the result is also a primitive int, then Java has a special interface for it: IntBinaryOperator. If you look at the code from Stephan and Mike, you see that this is what they use. They have an IntBinaryOperator f(x, y) = x + y, and given three ints a, b, c they test whether f(a, b) = a + b is equal to c.

IntBinaryOperator is a functional interface, with the abstract method: boolean apply(int x, int y). In a former life (i.e. before java 8), we had to use this to implement that interface:

Quite a mouthful! Fortunately, java 8 made it possible to specify that in a much shorter way:

Instead of asking whether f(a, b) == c, for some f, a, b, c, we can equivalently ask: is it true that for some integers a, b, c it holds that the expression: x + y == z, is true when applied to a, b and c?

A function in java that asks whether some expression is true or false, is called a Predicate, if the expression is about just one variable. For instance, we can ask whether the expression: x == 6 is true when x = 4.
In the same fashion, if we have an expression about two variables, we can ask whether that expression holds for two given variables a and b. For instance: if we have: x + y = 5, is this expression true when x = 3 and y = 2? Java has also a type for this; it is called a BiPredicate.

In this topic, we have three values x, y and z, and we have an expression E(x, y, z) = (x + y == z). We ask whether this expression is true for given a, b, c.
So, consequently, we are dealing with a TriPredicate here. But unfortunately, java has no interface for this. We have no alternative than to define our own TriPredicate interface. Luckily, that is very simple. All that is required is:

and with this interface, we are able to say:


Using the IntBinaryOperator saves some typing, but is equivalent.

Is this useful, you may ask? Well, as Mike rightly says, at least it is fun!

But foremost, it is a very useful training when you are studying for the OCPJP. My advice is to practise this as much as you can, make QuadFunctions and PentaConsumers, and then you will see that the subject is in fact easier than you might think. And, secondly, having passed the OCPJP 40 years ago, it is a nice way to rehears, see if you, old and wise(?), still understad the stuff.
 
Mike Simmons
Ranch Foreman
Posts: 3268
20
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:

...


I think those might give you some compilation problems... ;)
 
Piet Souris
Saloon Keeper
Posts: 3295
146
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, I DID write

Piet wrote:see if you, old and wise(?), still understad the stuff.

   
But indeed, here goes:

and

So, I guess I'll have to follow my own advice....    

 
salvin francis
Bartender
Posts: 2293
95
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:...unfortunately, java has no interface for this. We have no alternative than to define our own TriPredicate interface...
My advice is to practise this as much as you can, make QuadFunctions and PentaConsumers....



I am a bit curious as to why they (java language designers) stopped at BiPredicate. Maybe we should use Predicate instead and pass our own object having 3 field variables instead of defining a new interface ?
Not only do we get test() method, but we also get isEqual(), negate() and or() methods.
 
Campbell Ritchie
Marshal
Posts: 64666
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe they thought people wouldn't need tripredicates. But then they thought people wouldn't need all sort of things which are now to be found in Apache Commons or Google Guava, etc.
 
Piet Souris
Saloon Keeper
Posts: 3295
146
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried this:

And this works:

Now, finding a use for it. And: how do we specify generic types for a varargs argument?
 
salvin francis
Bartender
Posts: 2293
95
Google Web Toolkit Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was thinking along these lines:


 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!