Sobes.tech
Senior

1. Display unique combinations of user and product id for all purchases made by users before they were banned. Sort first by username, then by SKU. 2. Find users who made purchases totaling more than 5000 rubles. Display their id, first name, last name, and total purchase amount in the format: user id | first name | last name | total amount.

sobes.tech AI

Answer from AI

To solve the task in Go, let's assume we have data structures for purchases, users, and ban information. An approximate approach:

  1. Create structures to store information about purchases, users, and bans.
  2. Filter purchases made before the user's ban date.
  3. Collect unique pairs (user, SKU).
  4. Sort by username, then by SKU.
  5. For the second task, sum purchases by users and filter by sum > 5000.

Example code:

package main

import (
    "fmt"
    "sort"
    "time"
)

type Purchase struct {
    UserID   int
    SKU      string
    Amount   float64
    Date     time.Time
}

type User struct {
    ID        int
    FirstName string
    LastName  string
    BanDate   *time.Time // nil if not banned
}

func main() {
    users := []User{
        {ID: 1, FirstName: "Ivan", LastName: "Ivanov", BanDate: parseDatePtr("2023-05-10")},
        {ID: 2, FirstName: "Anna", LastName: "Petrova", BanDate: nil},
    }

    purchases := []Purchase{
        {UserID: 1, SKU: "A123", Amount: 2000, Date: parseDate("2023-05-01")},
        {UserID: 1, SKU: "B456", Amount: 3500, Date: parseDate("2023-05-09")},
        {UserID: 1, SKU: "A123", Amount: 1500, Date: parseDate("2023-05-11")}, // after ban
        {UserID: 2, SKU: "C789", Amount: 6000, Date: parseDate("2023-05-05")},
    }

    // 1. Unique combinations of user + SKU before ban
    type userSKU struct {
        UserName string
        SKU      string
    }
    uniqueMap := make(map[userSKU]struct{})

    userMap := make(map[int]User)
    for _, u := range users {
        userMap[u.ID] = u
    }

    for _, p := range purchases {
        user := userMap[p.UserID]
        if user.BanDate != nil && p.Date.After(*user.BanDate) {
            continue // purchase after ban
        }
        key := userSKU{UserName: user.FirstName, SKU: p.SKU}
        uniqueMap[key] = struct{}{}
    }

    var uniqueList []userSKU
    for k := range uniqueMap {
        uniqueList = append(uniqueList, k)
    }

    sort.Slice(uniqueList, func(i, j int) bool {
        if uniqueList[i].UserName == uniqueList[j].UserName {
            return uniqueList[i].SKU < uniqueList[j].SKU
        }
        return uniqueList[i].UserName < uniqueList[j].UserName
    })

    fmt.Println("Unique user and SKU combinations before ban:")
    for _, v := range uniqueList {
        fmt.Printf("%s | %s\n", v.UserName, v.SKU)
    }

    // 2. Users with total purchases > 5000
    sumMap := make(map[int]float64)
    for _, p := range purchases {
        sumMap[p.UserID] += p.Amount
    }

    fmt.Println("\nUsers with total purchases > 5000:")
    for id, sum := range sumMap {
        if sum > 5000 {
            u := userMap[id]
            fmt.Printf("%d | %s | %s | %.2f\n", u.ID, u.FirstName, u.LastName, sum)
        }
    }
}

func parseDate(s string) time.Time {
    t, _ := time.Parse("2006-01-02", s)
    return t
}

func parseDatePtr(s string) *time.Time {
    t := parseDate(s)
    return &t
}

This code demonstrates the logic for solving both tasks.