Skip to content
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
100 changes: 93 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,96 @@
# 99Tech Code Challenge #1 #
## Problem 1: Three Ways to Sum to N
**Solutions**:

Note that if you fork this repository, your responses may be publicly linked to this repo.
Please submit your application along with the solutions attached or linked.
1. **Iterative Loop (O(n))** - Traditional for-loop approach
- Handles negative numbers and decimals (floors to integer)
- Simple and straightforward implementation

It is important that you minimally attempt the problems, even if you do not arrive at a working solution.
2. **Mathematical Formula (O(1))** - Uses Gauss's formula: `n * (n + 1) / 2`
- Most efficient solution with constant time complexity
- Handles edge cases (negative numbers, decimals)
- Can handle very large numbers efficiently (e.g., `Number.MAX_SAFE_INTEGER`)

## Submission ##
You can either provide a link to an online repository, attach the solution in your application, or whichever method you prefer.
We're cool as long as we can view your solution without any pain.
3. **Recursion (O(n))** - Recursive approach
- Functional programming style
- Note: May cause stack overflow for very large numbers

**Assumptions**:
- Negative numbers return 0
- Decimals are floored to integers (e.g., 5.99 → 5)
- Zero returns 0

---

## Problem 2: Currency Swap Application

**Key Features**:

- **Bidirectional currency conversion** - Enter amount in either field, automatically calculates the other
- **Token selection with icons** - Dropdown selector with token images from Switcheo repository
- **Real-time price fetching** - Fetches live token prices from API
- **Form validation** - Input validation with error messages
- **Responsive design** - Works on all screen sizes (320px+)
- **Loading states** - Loading indicators during API calls and form submission
- **Token swap** - Quick swap between from/to tokens
- **Exchange rate display** - Shows current exchange rate between selected tokens

**Tech Stack**:

- **React 18** + Lucide React + **TypeScript** + **Vite**
- **Tailwind CSS** - Utility-first CSS framework
- **Custom React Hooks** - `useTokenPrices` for data fetching
- **Environment Variables** - Configurable token icon base URL

**Setup & Run**:

```bash
cd src/problem2
npm install
npm run dev
```

**[Deployment Demo URL https://99-code-challenge-eight.vercel.app/](https://99-code-challenge-eight.vercel.app/)**

**Preview**

<img width="550" height="589" alt="image" src="https://github.com/user-attachments/assets/e5e40399-804c-4c01-a069-99f94984b9e9" />


**Implementation**:

- **Type Safety**: Full TypeScript implementation with proper interfaces and types
- **Performance**: Uses `useMemo` and `useCallback` for optimization
- **Error Handling**: Comprehensive error handling for API failures
- **Accessibility**: Proper ARIA labels and keyboard navigation
- **Code Quality**: Modular component structure, clean separation of concerns

---

## Problem 3: Messy React Code Analysis & Refactoring

**Issues Identified & Fixed**:

1. **Type Safety Issues**:
- Used `any` type for blockchain parameter
-> Created `BlockchainName` type and `BlockchainEnum` for type safety

2. **Logic Errors**:
- Incorrect filter logic (`lhsPriority > -99` used undefined variable)
- Wrong filter condition (should filter `amount > 0`, not `<= 0`)
-> Fixed filter to properly check priority and positive amounts

3. **Performance Issues**:
- Unnecessary `prices` dependency in `useMemo` for sorting
- Missing `useMemo` for `formattedBalances` and `rows`
-> Removed redundant dependencies, added proper memoization

4. **Code Quality**:
- Used index as React key (anti-pattern)
- Inconsistent formatting (`toFixed()` vs `toFixed(2)`)
- Missing `children` in return statement
-> Used composite key (`currency-blockchain`), proper formatting, included children

5. **Best Practices**:
- `getPriority` not memoized
- Inefficient sort comparison
-> Memoized `getPriority` with `useCallback`, simplified sort logic
Empty file removed src/problem1/.keep
Empty file.
58 changes: 58 additions & 0 deletions src/problem1/problem1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
My assumptions:
- If n is negative, return result = 0
- If n is 0, return result = 0
- Assume n is 5.99, it will be converted to 5
*/

// O(n)
// The first approach that I thought: using loop
function sum_to_n_a(n: number): number {
let result = 0;
for (let i = 1; i <= n; i++) {
result += i;
}
return result;
};

// O(1)
// The second approach that I thought: using the formula for sum of first n natural numbers
function sum_to_n_b(n: number): number {
if (n <= 0) return 0;
n = Math.floor(n); // Assume n is 5.99, it will be converted to 5
return (n * (n + 1)) / 2;
};

// O(n)
// The third approach that I thought: using recursion
function sum_to_n_c(n: number): number {
if (n <= 0) return 0;
n = Math.floor(n); // Assume n is 5.99, it will be converted to 5
return n + sum_to_n_c(n - 1);
};

// sum_to_n_a()
console.log(sum_to_n_a(-1)) // 0
console.log(sum_to_n_a(0)) // 0
console.log(sum_to_n_a(5.99)) // 15
console.log(sum_to_n_a(5)) // 15
// console.log(sum_to_n_a(Number.MAX_SAFE_INTEGER)) // very slow, but still give the correct result. I will comment this line in case it makes the test run too long

// sum_to_n_b()
console.log(sum_to_n_b(-1)) // 0
console.log(sum_to_n_b(0)) // 0
console.log(sum_to_n_b(5.99)) // 15
console.log(sum_to_n_b(5)) // 15
console.log(sum_to_n_b(Number.MAX_SAFE_INTEGER)) // very fast, give the correct result - 4.0564819207303336e+31

// sum_to_n_c()
console.log(sum_to_n_c(-1)) // 0
console.log(sum_to_n_c(0)) // 0
console.log(sum_to_n_c(5.99)) // 15
console.log(sum_to_n_c(5)) // 15
// console.log(sum_to_n_c(Number.MAX_SAFE_INTEGER)) // Max call stack size exceeded

/*
There is other approaches: While Loop, Bitwise Operators,...
I thought using the Formula/Bitwise Operators method (O(1)) is the fastest and efficient.
*/
2 changes: 2 additions & 0 deletions src/problem2/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VITE_TOKEN_ICON_BASE_URL=https://raw.githubusercontent.com/Switcheo/token-icons/main/tokens/
VITE_TOKEN_PRICES_API_URL=https://interview.switcheo.com/prices.json
4 changes: 4 additions & 0 deletions src/problem2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.env
node_modules
dist
build
29 changes: 7 additions & 22 deletions src/problem2/index.html
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
<html>

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fancy Form</title>

<!-- You may add more stuff here -->
<link href="style.css" rel="stylesheet" />
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Currency Swap</title>
</head>

<body>

<!-- You may reorganise the whole HTML, as long as your form achieves the same effect. -->
<form onsubmit="return !1">
<h5>Swap</h5>
<label for="input-amount">Amount to send</label>
<input id="input-amount" />

<label for="output-amount">Amount to receive</label>
<input id="output-amount" />

<button>CONFIRM SWAP</button>
</form>
<script src="script.js"></script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

</html>
Loading