Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

develop into master: Challenges | Extra Challenge completed #3

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
93 changes: 79 additions & 14 deletions src/main/java/ChallengeStream.java
Original file line number Diff line number Diff line change
@@ -1,49 +1,114 @@
/* (C)2024 */
import java.util.List;

import mocks.CallCostObject;
import mocks.CallSummary;
import mocks.CardWinner;
import mocks.TotalSummary;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: usually imports are ordered by putting first libraries (either external or from the STL) and then local imports from other directories.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rearranged on 32577dd

public class ChallengeStream {

/**
* One stack containing five numbered cards from 0-9 are given to both players. Calculate which hand has winning number.
* The winning number is calculated by which hard produces the highest two-digit number.
*
* <p>
* calculateWinningHand([2, 5, 2, 6, 9], [3, 7, 3, 1, 2]) ➞ true
* P1 can make the number 96
* P2 can make the number 73
* P1 win the round since 96 > 73
*
* P1 can make the number 96
* P2 can make the number 73
* P1 win the round since 96 > 73
* <p>
* The function must return which player hand is the winner and the two-digit number produced. The solution must contain streams.
*
* @param player1 hand, player2 hand
* @param player1 hand, player2 hand
*/
public CardWinner calculateWinningHand(List<Integer> player1, List<Integer> player2) {
// YOUR CODE HERE...
return new CardWinner();
var player1Hand = player1.stream()
.sorted(Comparator.comparing((Integer i) -> i).reversed())
.distinct()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried about this distinct, what if our hand was all the same digits? We would end up with a stream that has only one digit, which is incorrect, because all the other cards are still valid, e.x

[1,2,3,4,5] vs [5,5,5,5,5] 

The winning hand for the left player is 54, while the winning hand for the right should be 55, with distinct I'm thinking you would get only 5

Copy link
Author

@ferodrigop ferodrigop Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored on 32577dd , then tested scenario described in description and passed

.limit(2)
.map(Object::toString)
.collect(Collectors.joining(""));

var player2Hand = player2.stream()
.sorted(Comparator.comparing((Integer i) -> i).reversed())
.distinct()
.limit(2)
.map(Object::toString)
.collect(Collectors.joining(""));

int player1Total = Integer.parseInt(player1Hand);
int player2Total = Integer.parseInt(player2Hand);

return new CardWinner(
player1Total == player2Total ? "TIE" : player1Total > player2Total ? "P1" : "P2",
Math.max(player1Total, player2Total)
);
}

/**
* Design a solution to calculate what to pay for a set of phone calls. The function must receive an
* array of objects that will contain the identifier, type and duration attributes. For the type attribute,
* the only valid values are: National, International and Local
*
* <p>
* The criteria for calculating the cost of each call is as follows:
*
* <p>
* International: first 3 minutes $ 7.56 -> $ 3.03 for each additional minute
* National: first 3 minutes $ 1.20 -> $ 0.48 per additional minute
* Local: $ 0.2 per minute.
*
* <p>
* The function must return the total calls, the details of each call (the detail received + the cost of the call)
* and the total to pay taking into account all calls. The solution must be done only using streams.
*
* @param {Call[]} calls - Call's information to be processed
*
* @returns {CallsResponse} - Processed information
*/
public TotalSummary calculateCost(List<CallCostObject> costObjectList) {
// YOUR CODE HERE...
return new TotalSummary();
var mainStream = costObjectList.stream()
.filter(
call -> call.getType().equals("International")
|| call.getType().equals("National")
|| call.getType().equals("Local")
)
.collect(Collectors.groupingBy(CallCostObject::getType));


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This group by operation seems a bit redundant, you could achieve the same with a map since you're just doing a flatMap later on in L79

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed and simplified on 32577dd

var callSummary = mainStream.values().stream().flatMap(
list -> list.stream().map(
callCostObject -> {
int extraMinutes = 0;
int duration = callCostObject.getDuration();
if (duration > 3 && !callCostObject.getType().equals("Local")) {
extraMinutes = duration - 3;
duration = 3;
}

double totalCost = switch (callCostObject.getType()) {
case "International" ->
Double.parseDouble(String.format("%.2f", (duration * 7.56) + (extraMinutes * 3.03)));
case "National" ->
Double.parseDouble(String.format("%.2f", (duration * 1.20) + (extraMinutes * 0.48)));
case "Local" -> Double.parseDouble(String.format("%.2f", (duration * 0.2)));
default -> 0D;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Similar comment as here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored on 32577dd including a new method which performs the calculations

};

return new CallSummary(
callCostObject,
totalCost
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this return could be a single line of code, not worth splitting it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored on 32577dd

}
)
).toList();

return new TotalSummary(
callSummary,
callSummary.size(),
callSummary.stream()
.mapToDouble(CallSummary::getTotalCost)
.sum()
);
}
}
88 changes: 74 additions & 14 deletions src/main/java/Challenges.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* (C)2024 */
import java.util.Collections;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/* (C)2024 */
public class Challenges {
Expand All @@ -20,9 +24,13 @@ public class Challenges {
***** */

public String readableTime(Integer seconds) {
// YOUR CODE HERE...
return "";
long h = TimeUnit.SECONDS.toHours(seconds);
long m = TimeUnit.SECONDS.toMinutes(seconds) - TimeUnit.HOURS.toMinutes(h);
long s = seconds - TimeUnit.HOURS.toSeconds(h) - TimeUnit.MINUTES.toSeconds(m);

return String.format("%02d:%02d:%02d", h, m, s);
}

;

/* *****
Expand All @@ -44,9 +52,22 @@ public String readableTime(Integer seconds) {

public String[] circularArray(int index) {
String[] COUNTRY_NAMES = {"Germany", "Norway", "Island", "Japan", "Israel"};
// YOUR CODE HERE...

index = index % COUNTRY_NAMES.length;

String[] tempArray = new String[COUNTRY_NAMES.length];

int numberOfElementsToCopy = COUNTRY_NAMES.length - index;

// for example: if I copy 4 elements that means, based on the index position of arrays,
// the 4th position will be available because position 0, 1, 2 and 3 are used since I copied 4 elements
System.arraycopy(COUNTRY_NAMES, index, tempArray, 0, numberOfElementsToCopy);
System.arraycopy(COUNTRY_NAMES, 0, tempArray, numberOfElementsToCopy, COUNTRY_NAMES.length - numberOfElementsToCopy);

COUNTRY_NAMES = tempArray.clone();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: If COUNTRY_NAMES were to be a static variable you would be breaking this function each time you called it, returning tempArray.clone directly would be less error prone

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored to directly return it on e235614

return COUNTRY_NAMES;
}

;

/* *****
Expand All @@ -70,9 +91,19 @@ public String[] circularArray(int index) {
***** */

public String ownPower(int number, int lastDigits) {
// YOUR CODE HERE...
return "";
BigInteger powResult = BigInteger.ZERO;

for (int i = 1; i <= number; i++) {
BigInteger powNumber = new BigInteger(String.valueOf(i)).pow(i);

powResult = powResult.add(powNumber);
}

String result = String.valueOf(powResult);

return result.substring(result.length() - lastDigits);
Copy link
Collaborator

@quebin31 quebin31 Nov 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Think about the solution with modulo described here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored solution and used modulo on e235614

}

;

/* *****
Expand All @@ -93,8 +124,21 @@ A factorial (x!) means x! * (x - 1)... * 3 * 2 * 1.
***** */

public Integer digitSum(int n) {
// YOUR CODE HERE...
return 1;
BigInteger totalFactorial = BigInteger.ONE;

for (int i = n; i >= 1; i--) {
totalFactorial = totalFactorial.multiply(BigInteger.valueOf(i));
}

char[] digits = String.valueOf(totalFactorial).toCharArray();

BigDecimal sum = BigDecimal.ZERO;

for (char c : digits) {
sum = sum.add(new BigDecimal(String.valueOf(c)));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Similar comment as here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored solution and used modulo and division on e235614


return sum.intValue();
}

/**
Expand All @@ -104,11 +148,19 @@ public Integer digitSum(int n) {
* H = 72, the sum of H 72 and 33 gives 105 which ascii value is i;
* The function must return the string encoded using the encryption function below.
*
* @param ascivalues hand, player2 hand
* @param ascivalues hand, player2 hand
*/
public String decrypt(List<Integer> ascivalues) {
// YOUR CODE HERE...
return "";
int number = 0;

StringBuilder result = new StringBuilder();

for (Integer num : ascivalues) {
number += num;
result.append((char) number);
}
Comment on lines +156 to +159
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanest one yet!


return result.toString();
}

/**
Expand All @@ -118,10 +170,18 @@ public String decrypt(List<Integer> ascivalues) {
* // H = 72, the difference between the H and e is 29
* The function must return an array of integer ascii values.
*
* @param text hand, player2 hand
* @param text hand, player2 hand
*/
public List<Integer> encrypt(String text) {
// YOUR CODE HERE...
return Collections.emptyList();
char[] chars = text.toCharArray();
int value = 0;
List<Integer> result = new ArrayList<>();

for (char c : chars) {
result.add(((int) c) - value);
value = c;
}

return result;
}
}