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
56 changes: 56 additions & 0 deletions src/problem4/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Problem 4: Three ways to sum to n
* Summation from 1 to n: sum_to_n(5) === 1 + 2 + 3 + 4 + 5 === 15
* Handles positive integers, negative integers, and zero.
*/

/**
* Implementation A: Gauss closed-form formula
*
* For n >= 0: n * (n + 1) / 2 (standard arithmetic series)
* For n < 0: -(|n| * (|n| + 1) / 2) (symmetric signed sum toward -1)
*
* Time complexity: O(1) — single arithmetic expression, no iteration
* Space complexity: O(1) — no additional memory
*/
export function sum_to_n_a(n: number): number {
const abs = Math.abs(n);
return Math.sign(n) * (abs * (abs + 1)) / 2;
}

/**
* Implementation B: Iterative loop
*
* Accumulates the sum by iterating from 1 to n (or n to -1 for negatives).
*
* Time complexity: O(n) — linear, one pass through all integers up to n
* Space complexity: O(1) — only a single accumulator variable
*/
export function sum_to_n_b(n: number): number {
let sum = 0;
if (n >= 0) {
for (let i = 1; i <= n; i++) {
sum += i;
}
} else {
for (let i = -1; i >= n; i--) {
sum += i;
}
}
return sum;
}

/**
* Implementation C: Recursive
*
* Recursively sums by reducing n toward 0 on each call.
*
* Time complexity: O(n) — n recursive calls on the call stack
* Space complexity: O(n) — each call frame is kept on the stack until unwinding;
* this can cause a stack overflow for very large |n|
*/
export function sum_to_n_c(n: number): number {
if (n === 0) return 0;
if (n > 0) return n + sum_to_n_c(n - 1);
return n + sum_to_n_c(n + 1);
}
3 changes: 3 additions & 0 deletions src/problem5/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PORT=3000
NODE_ENV=development
DB_PATH=./data/dev.db
6 changes: 6 additions & 0 deletions src/problem5/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
dist/
.env
*.db
*.db-shm
*.db-wal
1 change: 1 addition & 0 deletions src/problem5/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-peer-deps=true
201 changes: 201 additions & 0 deletions src/problem5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Problem 5 – Crude Server

A production-quality REST API built with **Express.js**, **TypeScript**, **TypeORM**, and **SQLite**.

## Stack

| Layer | Technology |
|---|---|
| Framework | Express.js |
| Language | TypeScript |
| ORM | TypeORM |
| Database | SQLite (via sqlite3) |
| Validation | Zod |
| Testing | Jest + ts-jest |

## Project Structure

```
src/
├── app.ts # Express app setup
├── server.ts # Entry point
├── config/
│ ├── env.ts # Environment variables
│ └── database.ts # TypeORM DataSource
├── modules/
│ └── resource/
│ ├── resource.model.ts # TypeORM entity
│ ├── resource.dto.ts # Types / interfaces
│ ├── resource.validation.ts # Zod schemas
│ ├── resource.repository.ts # Database queries
│ ├── resource.service.ts # Business logic
│ ├── resource.controller.ts # Request / response handling
│ └── resource.routes.ts # Express router
├── common/
│ ├── middleware/
│ │ ├── error.middleware.ts # Centralized error handler
│ │ └── validate.middleware.ts # Zod validation middleware
│ ├── utils/logger.ts
│ ├── types/express.d.ts
│ └── constants/httpStatus.ts
├── routes/
│ └── index.ts # Combines all routes
└── database/
└── seed/index.ts # Seed data
```

## Prerequisites

- Node.js >= 18
- npm

## Configuration

Copy `.env.example` to `.env`:

```bash
cp .env.example .env
```

| Variable | Default | Description |
|---|---|---|
| `PORT` | `3000` | HTTP port |
| `NODE_ENV` | `development` | Environment |
| `DB_PATH` | `./data/dev.db` | SQLite file path |

## Running

### Development

```bash
npm install
npm run dev
```

The database tables are created automatically on first start (`synchronize: true`).

### Production

```bash
npm run build
npm start
```

### Seed (optional)

```bash
npm run db:seed
```

## Testing

```bash
# Run all tests
npm test

# Watch mode
npm run test:watch
```

### Test coverage

| File | What is tested |
|---|---|
| `resource.validation.ts` | All Zod schemas — valid input, edge cases, cross-field rules (`minPrice ≤ maxPrice`) |
| `resource.service.ts` | All service methods with mocked repository — happy path and 404 error cases |

Tests are located in `src/modules/resource/__tests__/`.

## API Reference

Base URL: `http://localhost:3000/api`

### List resources

```
GET /resources
```

Query parameters:

| Param | Type | Description |
|---|---|---|
| `name` | string | Partial name match |
| `minPrice` | number | Minimum price |
| `maxPrice` | number | Maximum price |
| `page` | number | Page number (default: 1) |
| `limit` | number | Page size (default: 20, max: 100) |

**Response**
```json
{
"data": [...],
"total": 10,
"page": 1,
"limit": 20,
"totalPages": 1
}
```

### Get resource

```
GET /resources/:id
```

### Create resource

```
POST /resources
Content-Type: application/json

{
"name": "Laptop",
"description": "High performance laptop",
"price": 999.99
}
```

**Response:** `201 Created`

### Update resource

```
PATCH /resources/:id
Content-Type: application/json

{
"price": 899.99
}
```

### Delete resource

```
DELETE /resources/:id
```

**Response:** `204 No Content`

## Example curl commands

```bash
# Create
curl -X POST http://localhost:3000/api/resources \
-H "Content-Type: application/json" \
-d '{"name":"Laptop","description":"Gaming laptop","price":999.99}'

# List with filters
curl "http://localhost:3000/api/resources?minPrice=100&maxPrice=1000&page=1&limit=10"

# Get by id
curl http://localhost:3000/api/resources/1

# Update
curl -X PATCH http://localhost:3000/api/resources/1 \
-H "Content-Type: application/json" \
-d '{"price":899.99}'

# Delete
curl -X DELETE http://localhost:3000/api/resources/1
```
13 changes: 13 additions & 0 deletions src/problem5/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Config } from 'jest';

const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
rootDir: 'src',
testMatch: ['**/__tests__/**/*.test.ts'],
moduleNameMapper: {
'^reflect-metadata$': '<rootDir>/../node_modules/reflect-metadata',
},
};

export default config;
Loading