Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

NW-6 | Fikret Ellek | JS1| [TECH ED] Complete week 3 exercises | WEEK-3 #193

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion week-3/debug/format-as-12-hours.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function formatAs12HourClock(time) {
if (Number(time.slice(0, 2)) > 12) {
return `${Number(time.slice(0, 2)) - 12}:00 pm`;
return `${Number(time.slice(0, 2)) - 12}:${time.slice(3, 5)} pm`;
}
return `${time} am`;
}
Expand All @@ -23,6 +23,15 @@ console.assert(
targetOutput2
);

const currentOutput3 = formatAs12HourClock("17:42");
const targetOutput3 = "5:42 pm";
console.assert(
currentOutput3 === targetOutput3,
"current output: %s, target output: %s",
currentOutput3,
targetOutput3
);

// formatAs12HourClock currently has a 🐛

// a) Write an assertion to check the return value of formatAs12HourClock when it is called with an input "17:42"
Expand Down
24 changes: 24 additions & 0 deletions week-3/implement/get-angle-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,27 @@
// Identify Reflex Angles:
// When the angle is greater than 180 degrees and less than 360 degrees,
// Then the function should return "Reflex angle"

function getAngleType(angle) {
let angleType = "";

if (angle < 90) {
angleType = "Acute";
} else if (angle === 90) {
angleType = "Right";
} else if (angle < 180) {
angleType = "Obtuse";
} else if (angle === 180) {
angleType = "Straight";
} else if (angle > 180) {
angleType = "Reflex";
}

return `${angleType} angle`;
}

console.assert(getAngleType(50) === "Acute angle", "1");
console.assert(getAngleType(90) === "Right angle", "2");
console.assert(getAngleType(170) === "Obtuse angle", "3");
console.assert(getAngleType(180) === "Straight angle", "4");
console.assert(getAngleType(290) === "Reflex angle", "5");
44 changes: 44 additions & 0 deletions week-3/implement/get-card-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,47 @@
// Given a card with an invalid rank (neither a number nor a recognized face card),
// When the function is called with such a card,
// Then it should throw an error indicating "Invalid card rank."

function getCardValue(cards) {
const number = [
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J",
"Q",
"K",
"A",
];
const type = ["♣", "♦", "♥", "♠"];
let num = cards.slice(0, -1);

if (number.includes(num) && type.includes(cards.slice(-1))) {
if (num === "A") {
result = 11;
} else if (num === "J") {
result = 10;
} else if (num === "Q") {
result = 10;
} else if (num === "K") {
result = 10;
} else {
result = Number(num);
}
return result;
} else {
return "Invalid card rank.";
}
}
Comment on lines +49 to +68
Copy link
Contributor

Choose a reason for hiding this comment

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

This solution will definitely work! Though we can make it more effective.
Try rewriting it using Objects instead of Arrays for storing cards and their values like:

const cards = {
  '2': 2,
  '3': 3,
  ...
}

We can use Object for card types too.
In this case we won't need to use includes and iterate through the whole list of cards every time.

Copy link
Author

Choose a reason for hiding this comment

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

we can just return

return card[cards.slice(0, -1)] && type[cards.slice(-1)] ? number[cards.slice(0, -1)] : "Invalid card rank." ;

🤯


console.assert(getCardValue("A♠") === 11, "11");
console.assert(getCardValue("5♠") === 5, "5");
console.assert(getCardValue("J♥") === 10, "10j");
console.assert(getCardValue("Q♠") === 10, "10q");
console.assert(getCardValue("K♠") === 10, "10k");
console.assert(getCardValue("2a") === "Invalid card rank.", "6");
39 changes: 34 additions & 5 deletions week-3/implement/is-proper-fraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,60 @@
// Fractions: https://www.bbc.co.uk/bitesize/topics/zt9n6g8/articles/zjxpp4j
// Written here like this: 1/2 == Numerator/Denominator

function isProperFraction(numerator, denominator) {
const fraction = numerator / denominator;
if (denominator === 0) {
return "Error (Denominator cannot be zero)";
} else if (
(fraction < 1 && fraction > 0) ||
(fraction > -1 && fraction < 0)
) {
return true;
} else {
return false;
}
}
Comment on lines +10 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

It's all correct. But I have some ideas how to make it a little shorter:

  if (denominator === 0) {
    return "Error (Denominator cannot be zero)";
  }
  
  return (fraction > -1 && fraction < 1 && fraction !== 0);
}

Let me explain you a couple of things here.
First, If the first check is true (denominator === 0) then the function returns an error and the rest of it won't be performed. If it is false then the function continue to work anyway. It means that we don't really need else here.

Second point is that comparison like fraction < 1 results in either true or false. It mean that we don't really need to write something like:

if (fraction > 1) {
  return true;
} else {
  return false;
}

We can just write return fraction > 1 and that's it.

In this task we have few conditions to check, but the approach may be the same: return (fraction > -1 && fraction < 1 && fraction !== 0); because the result of these 3 checks will be either true or false.

Copy link
Author

Choose a reason for hiding this comment

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

Using return to break the loop. That is brilliant 🤩 . I understand if the comparison returns true or false, there is no need to check with if statement.


// Acceptance criteria:

// Proper Fraction check:
// Input: numerator = 2, denominator = 3
// target output: true
// Explanation: The fraction 2/3 is a proper fraction, where the numerator is less than the denominator. The function should return true.

console.assert(
isProperFraction(2, 3) === true,
"proper fraction check failed, input 2, 3"
);
// Improper Fraction check:
// Input: numerator = 5, denominator = 2
// target output: false
// Explanation: The fraction 5/2 is an improper fraction, where the numerator is greater than or equal to the denominator. The function should return false.

console.assert(
isProperFraction(5, 2) === false,
"improper fraction check failed, input 5, 2"
);
// Zero Denominator check:
// Input: numerator = 3, denominator = 0
// No target output: Error (Denominator cannot be zero)
// Explanation: The function should throw an error when the denominator is zero, as it's not a valid fraction.

console.assert(
isProperFraction(3, 0) === "Error (Denominator cannot be zero)",
"zero dominator check failed, input 3, 0"
);
// Negative Fraction check:
// Input: numerator = -4, denominator = 7
// target output: true
// Explanation: The fraction -4/7 is a proper fraction because the absolute value of the numerator (4) is less than the denominator (7). The function should return true.

console.assert(
isProperFraction(-4, 7) === true,
"negative fraction check failed, input -4, 7"
);
// Equal Numerator and Denominator check:
// Input: numerator = 3, denominator = 3
// target output: false
// Explanation: The fraction 3/3 is not a proper fraction because the numerator is equal to the denominator. The function should return false.

console.assert(
isProperFraction(3, 3) === false,
"equal numerator and denominator check failed, input 3, 3"
);
// These acceptance criteria cover a range of scenarios to ensure that the isProperFraction function handles both proper and improper fractions correctly and handles potential errors such as a zero denominator.
25 changes: 23 additions & 2 deletions week-3/implement/is-valid-triangle.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
// Implement a function isValidTriangle
function isValidTriangle(a, b, c) {
if (a <= 0 && b <= 0 && c <= 0) {
return false;
} else {
if (a + b > c && b + c > a && c + a > b) {
return true;
} else {
return false;
}
}
}
Comment on lines +3 to +12
Copy link
Contributor

Choose a reason for hiding this comment

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

This will definitely work! But again it may be improved:

  1. a <= 0 && b <= 0 && c <= 0 - this check means that if all 3 sides are equal to 0, then it's not a triangle. But in fact it's not a triangle if either of the sides is equal to 0. Either a, or b, or c.

  2. As for the rest of this function, could you try refactor it yourself using my advice from is-proper-fraction.js task?

Copy link
Author

Choose a reason for hiding this comment

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

so it's gonna be like

function isValidTriangle(a, b, c) {
  if (a <= 0 && b <= 0 && c <= 0) {
      return false;
    }
  return (a + b > c && b + c > a && c + a > b)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

What I actually meant was using || instead of && in the first if check:

  if (a <= 0 || b <= 0 || c <= 0) {
    return false;
  } else {
    return (a + b > c && b + c > a && c + a > b); // for this line your refactoring is perfect!

or... we can even make it shorter:

return !(a <= 0 || b <= 0 || c <= 0) || (a + b > c && b + c > a && c + a > b);

but the last may be not very clear.


// 🗝️ Terms
// the Triangle Inequality says: the sum of any two sides is always greater than the third side.
Expand All @@ -25,16 +36,26 @@
// Given the side lengths a, b, and c,
// When the sum of any two side lengths is less than or equal to the length of the third side (i.e., a + b <= c, a + c <= b, b + c <= a),
// Then it should return false because these conditions violate the Triangle Inequality, which states that the sum of the lengths of any two sides of a triangle must be greater than the length of the third side.

console.assert(
isValidTriangle(3, 3, 6) === false && isValidTriangle(2, 3, 6) === false,
"When the sum of any two side lengths is less than or equal to the length of the third side"
);
// scenario: invalid triangle
// Check for Valid Input:
// Given the sides a, b, and c,
// When any of the sides are less than or equal to zero,
// Then it should return false because a triangle cannot have zero or negative side lengths.
console.assert(
isValidTriangle(3, 3, -3) === false && isValidTriangle(1, 1, 0) === false,
"When any of the sides are less than or equal to zero"
);

// scenario: valid triangle
// Given valid side lengths where the sum of any two sides is greater than the third side,
// When the function is called with these values as input,
// Then it should return true because the input forms a valid triangle.

console.assert(
isValidTriangle(3, 3, 3) === true && isValidTriangle(3, 4, 5) === true,
"When valid side lengths where the sum of any two sides is greater than the third side"
);
// This specification outlines the behavior of the isValidTriangle function for different input scenarios, ensuring it properly checks for invalid side lengths and whether they form a valid triangle according to the Triangle Inequality Theorem.
35 changes: 35 additions & 0 deletions week-3/refactor/format-as-12-hours.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,38 @@
// Store this expression in a variable and reference it twice in the function in the correct place

// Explain why it makes more sense to store this expression in a variable

function formatAs12HourClock(time) {
const hour = time.slice(0, 2);
if (Number(hour) > 12) {
return `${Number(hour) - 12}:${time.slice(3, 5)} pm`;
Comment on lines +9 to +11
Copy link
Contributor

Choose a reason for hiding this comment

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

Very good! But we still can improve it. Do we really need to call Number(hour) twice or we can do it only once somehow?

Copy link
Author

Choose a reason for hiding this comment

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

We can assign it to a variable and use it multiple times. I couldn't see it 😔

}
return `${time} am`;
}

const currentOutput = formatAs12HourClock("08:00");
const targetOutput = "08:00 am";
console.assert(
currentOutput === targetOutput,
"current output: %s, target output: %s",
currentOutput,
targetOutput
);

const currentOutput2 = formatAs12HourClock("23:00");
const targetOutput2 = "11:00 pm";
console.assert(
currentOutput2 === targetOutput2,
"current output: %s, target output: %s",
currentOutput2,
targetOutput2
);

const currentOutput3 = formatAs12HourClock("17:42");
const targetOutput3 = "5:42 pm";
console.assert(
currentOutput3 === targetOutput3,
"current output: %s, target output: %s",
currentOutput3,
targetOutput3
);
68 changes: 68 additions & 0 deletions week-3/stretch/rotate-char.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,74 @@

// Acceptance criteria:

function rotateCharacter(char, shift) {
const alphabetLower = [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
];
const alphabetUpper = [
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
if (alphabetLower.includes(char)) {
const value = (alphabetLower.indexOf(char) + shift) % 26;
return alphabetLower[value];
} else if (alphabetUpper.includes(char)) {
const value = (alphabetUpper.indexOf(char) + shift) % 26;
return alphabetUpper[value];
} else {
return char;
}
Comment on lines +68 to +76
Copy link
Contributor

Choose a reason for hiding this comment

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

This is good and definitely should work. Though it may be optimised in a few ways:

  1. For now each time we call the function rotateCharacter we check/iterate the same array of letters 2 times:
  • 1st time when we call includes
  • 2nd time when we call indexOf
    Can we avoid using includes at all in this task and just use only indexOf and only once?
    What this method returns us when there is no value we search in array?
  1. In the worst case (e.g. the argument is a number) we will check 2 arrays of letters before returning original value back. But I think we can use one array of letters (e.g. alphabetLower) instead of two if we utilise the string methods toLowerCase() and toUpperCase()

Copy link
Author

Choose a reason for hiding this comment

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

Ahh I see, yes it makes the code more efficient. So that way we will turn the chat in to lower case and then check if it is included in the lower case array. Then shift the char and return upper case or lower case. When there is no matching element (char is not a letter) in the array we will get -1 and return the char itself

}

// Given a character (char) and a shift value (shift),
// When the function rotateCharacter is called with these inputs,
// Then it should:
Expand Down