// 3. hét – A gyakorlati feladatok megoldásai
// Futtatás: go run ./h03/exercises
package main

import (
	"fmt"
	"math"
	"strings"
)

func average(a []int) float64 {
	sum := 0
	for _, v := range a {
		sum += v
	}
	return float64(sum) / float64(len(a))
}

func contains(a []int, x int) bool {
	for _, v := range a {
		if v == x {
			return true
		}
	}
	return false
}

func secondLargest(a []int) int {
	first, second := math.MinInt, math.MinInt
	for _, v := range a {
		if v > first {
			second, first = first, v
		} else if v > second && v != first {
			second = v
		}
	}
	return second
}

// removeDuplicates rendezett szeletből helyben; az új hosszt adja vissza.
func removeDuplicates(a []int) int {
	if len(a) == 0 {
		return 0
	}
	w := 1
	for r := 1; r < len(a); r++ {
		if a[r] != a[w-1] {
			a[w] = a[r]
			w++
		}
	}
	return w
}

// merge: két rendezett szelet összefésülése – O(n + m).
func merge(a, b []int) []int {
	c := make([]int, 0, len(a)+len(b))
	i, j := 0, 0
	for i < len(a) && j < len(b) {
		if a[i] <= b[j] {
			c = append(c, a[i])
			i++
		} else {
			c = append(c, b[j])
			j++
		}
	}
	c = append(c, a[i:]...)
	return append(c, b[j:]...)
}

func rowColSums(m [][]int) ([]int, []int) {
	rows, cols := make([]int, len(m)), make([]int, len(m[0]))
	for i := range m {
		for j := range m[i] {
			rows[i] += m[i][j]
			cols[j] += m[i][j]
		}
	}
	return rows, cols
}

func spiral(m [][]int) string {
	var sb strings.Builder
	top, bottom, left, right := 0, len(m)-1, 0, len(m[0])-1
	add := func(v int) { fmt.Fprintf(&sb, "%d ", v) }
	for top <= bottom && left <= right {
		for j := left; j <= right; j++ {
			add(m[top][j])
		}
		top++
		for i := top; i <= bottom; i++ {
			add(m[i][right])
		}
		right--
		if top <= bottom {
			for j := right; j >= left; j-- {
				add(m[bottom][j])
			}
			bottom--
		}
		if left <= right {
			for i := bottom; i >= top; i-- {
				add(m[i][left])
			}
			left++
		}
	}
	return strings.TrimSpace(sb.String())
}

func main() {
	a := []int{4, 9, 2, 9, 7, 1}
	fmt.Println("F1. average =", average(a))
	fmt.Println("F2. contains(7) =", contains(a, 7), ", contains(5) =", contains(a, 5))
	fmt.Println("F3. secondLargest =", secondLargest(a))
	s := []int{1, 1, 2, 3, 3, 3, 5}
	fmt.Println("F4. removeDuplicates ->", s[:removeDuplicates(s)])
	fmt.Println("F5. merge =", merge([]int{1, 4, 9}, []int{2, 3, 10, 11}))
	m := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
	r, c := rowColSums(m)
	fmt.Println("F6. sorösszegek =", r, ", oszlopösszegek =", c)
	fmt.Println("F7. spirál:", spiral(m))
}
