package main

import "fmt"

// Map transforms each element in a slice using the provided function
func Map[T any, U any](slice []T, fn func(T) U) []U {
	result := make([]U, len(slice))
	for i, v := range slice {
		result[i] = fn(v)
	}
	return result
}

// Reduce combines all elements in a slice into a single value
func Reduce[T any, U any](slice []T, initial U, fn func(U, T) U) U {
	acc := initial
	for _, v := range slice {
		acc = fn(acc, v)
	}
	return acc
}

func main() {
	// Test Map: Convert integers to strings
	numbers := []int{1, 2, 3, 4, 5}
	strings := Map(numbers, func(n int) string {
		return fmt.Sprintf("Number: %d", n)
	})
	fmt.Println("Mapped to strings:", strings)

	// Test Map: Square numbers
	squared := Map(numbers, func(n int) int {
		return n * n
	})
	fmt.Println("Squared numbers:", squared)

	// Test Map: Convert strings to their lengths
	words := []string{"go", "rust", "python", "javascript"}
	lengths := Map(words, func(s string) int {
		return len(s)
	})
	fmt.Println("Word lengths:", lengths)

	// Test Reduce: Sum of integers
	sum := Reduce(numbers, 0, func(acc int, n int) int {
		return acc + n
	})
	fmt.Println("Sum:", sum)

	// Test Reduce: Product of integers
	product := Reduce(numbers, 1, func(acc int, n int) int {
		return acc * n
	})
	fmt.Println("Product:", product)

	// Test Reduce: Concatenate strings
	sentence := Reduce(words, "", func(acc string, word string) string {
		if acc == "" {
			return word
		}
		return acc + " " + word
	})
	fmt.Println("Concatenated:", sentence)

	// Test Reduce: Find maximum value
	maxValues := []int{3, 7, 2, 9, 1, 5}
	max := Reduce(maxValues, maxValues[0], func(acc int, n int) int {
		if n > acc {
			return n
		}
		return acc
	})
	fmt.Println("Maximum:", max)
}
