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
Empty file removed src/problem1/.keep
Empty file.
53 changes: 53 additions & 0 deletions src/problem1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Problem 1: Three ways to sum to n

## Description
Provide 3 unique implementations of a function that calculates the summation of numbers from 1 to `n`.

**Input**: `n` - any integer.
**Output**: Summation to `n`.

## Assumptions
1. The result will always be less than `Number.MAX_SAFE_INTEGER`.
2. Input `n` should be a non-negative integer.
- If `n` is 0, a sum is 0.
- If `n` < 0, the function throws an error (based on standard summation definition 1...n, though mathematical definition might return 0 or be invalid, here strict validation is applied).

## Implementations

### 1. `sum_to_n_a`: Arithmetic Series Formula
Uses the mathematical formula for the sum of the first n integers:
\[ S_n = \frac{n(n+1)}{2} \]

- **Time Complexity**: O(1)—Constant time calculation.
- **Space Complexity**: O(1)—Constant space.
- **Pros**: Fastest and most efficient.
- **Cons**: Theoretical risk of intermediate overflow `n*(n+1)` if `n` is extremely large (close to `MAX_SAFE_INTEGER`).

### 2. `sum_to_n_b`: Iterative Loop
Uses a `for` loop to accumulate the sum from 1 to `n`.

- **Time Complexity**: O(n)—Linear time.
- **Space Complexity**: O(1)—Constant space.
- **Pros**: Robust, easy to read, no recursion stack limits.
- **Cons**: Slower than the formula for very large `n`.

### 3. `sum_to_n_c`: Recursion
Uses the recursive definition: `sum(n) = n + sum(n-1)`.

- **Time Complexity**: O(n)—Linear time.
- **Space Complexity**: O(n)—Linear space due to the call stack.
- **Pros**: Demonstrates functional programming concepts.
- **Cons**: In JavaScript, this is limited by the maximum call stack size (typically ~10,000 calls). Will throw `RangeError: Maximum call stack size exceeded` for large `n`.

## Usage
```javascript
import { sum_to_n_a } from './index'

console.log(sum_to_n_a(5)); // 15
```

## Testing
Run the test suite:
```bash
node src/problem1/test.js
```
31 changes: 31 additions & 0 deletions src/problem1/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { validateInput } from "./validation"

// Option A: Arithmetic Series Formula | O(1) time, O(1) space
export const sum_to_n_a = function(n) {
validateInput(n)

if (n === 0) return 0
return (n * (n + 1)) / 2
}

// Option B: Iterative Loop | O(n) time, O(1) space
export const sum_to_n_b = function(n) {
validateInput(n)

let sum = 0
for (let i = 1; i <= n; i++) {
sum += i
}
return sum
}

// Option C: Recursion | O(n) time, O(n) space (stack)
export const sum_to_n_c = function(n) {
if (n === 0) return 0
if (n === 1) return 1

validateInput(n)

if (n <= 1) return n
return n + sum_to_n_c(n - 1)
}
84 changes: 84 additions & 0 deletions src/problem1/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import assert from "assert"
import { sum_to_n_a, sum_to_n_b, sum_to_n_c } from "./index"

const functions = [
{ name: 'sum_to_n_a', fn: sum_to_n_a },
{ name: 'sum_to_n_b', fn: sum_to_n_b },
{ name: 'sum_to_n_c', fn: sum_to_n_c }
]

console.log("Starting Tests...\n")

let passed = 0
let failed = 0

function runTest(testName, action) {
try {
action()
console.log(`✅ [PASS] ${testName}`)
passed++
} catch (e) {
console.error(`❌ [FAIL] ${testName}`)
console.error(` Error: ${e.message}`)
failed++
}
}

functions.forEach(function(impl) {
const fn = impl.fn
const name = impl.name

console.log(`Testing implementation: ${name}`)

// Test Case 1: Standard Input
runTest(`${name}(5) should be 15`, function() {
assert.strictEqual(fn(5), 15)
})

// Test Case 2: Base Case 1
runTest(`${name}(1) should be 1`, function() {
assert.strictEqual(fn(1), 1)
})

// Test Case 3: Base Case 0
runTest(`${name}(0) should be 0`, function() {
assert.strictEqual(fn(0), 0)
})

// Test Case 4: Large Input (within stack limit for recursion)
runTest(`${name}(100) should be 5050`, function() {
assert.strictEqual(fn(100), 5050)
})

// Test Case 5: Negative Input
runTest(`${name}(-1) should throw Error`, function() {
assert.throws(function() {
return fn(-1)
}, /Input must be a non-negative integer/)
})

// Test Case 6: Non-integer Input
runTest(`${name}(5.5) should throw Error`, function() {
assert.throws(function() {
return fn(5.5)
}, /Input must be an integer/)
})

// Test Case 7: String Input
runTest(`${name}('5') should throw Error`, function() {
assert.throws(function() {
return fn('5')
}, /Input must be a number/)
})

console.log('---')
})

console.log(`\nTest Summary:`)
console.log(`Total: ${passed + failed}`)
console.log(`Passed: ${passed}`)
console.log(`Failed: ${failed}`)

if (failed > 0) {
process.exit(1)
}
23 changes: 23 additions & 0 deletions src/problem1/validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Validates the input n for the sum_to_n function.
*
* @param {any} n - The input to validate.
* @throws {Error} If the input is invalid.
*/
export const validateInput = function(n) {
if (typeof n !== 'number') {
throw new Error("Input must be a number")
}

if (!Number.isInteger(n)) {
throw new Error("Input must be an integer")
}

if (n < 0) {
throw new Error("Input must be a non-negative integer")
}

if (n > Number.MAX_SAFE_INTEGER) {
throw new Error("Input exceeds MAX_SAFE_INTEGER")
}
}
24 changes: 24 additions & 0 deletions src/problem2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
1 change: 1 addition & 0 deletions src/problem2/.husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lint-staged
73 changes: 73 additions & 0 deletions src/problem2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## React Compiler

The React Compiler is currently not compatible with SWC. See [this issue](https://github.com/vitejs/vite-plugin-react/issues/428) for tracking the progress.

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

```js
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...

// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,

// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```
54 changes: 54 additions & 0 deletions src/problem2/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noUselessFragments": "off"
},
"correctness": {
"useExhaustiveDependencies": "off"
},
"style": {
"useConsistentCurlyBraces": {
"level": "warn",
"fix": "safe"
}
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"recommended": true
}
}
},
"css": {
"parser": {
"tailwindDirectives": true
}
}
}
23 changes: 23 additions & 0 deletions src/problem2/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-mira",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"menuColor": "default",
"menuAccent": "subtle",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
Loading