Tarkibga o'tish

1. Slice — slice'larning ichki tuzilishi

Go'da massiv ([N]T) o'lchami qat'iy, slice ([]T) esa massivning bir qismiga «oyna»: ko'rsatkich, uzunlik (len) va sig'im (cap). Barcha masalalarda natijani fmt.Println bilan chiqarib, kutilgan natija bilan solishtiring.

Massiv va slice farqi

1. [5]int massiv e'lon qiling va uni boshqa o'zgaruvchiga o'zlashtiring. Nusxani o'zgartirib, asl massiv o'zgarmaganini ko'rsating. Xuddi shu tajribani []int slice bilan takrorlang va farqini izohlang.
Misol: a := [3]int{1, 2, 3}; b := a; b[0] = 9 → a = [1 2 3], b = [9 2 3]; slice bilan: a = [9 2 3], b = [9 2 3] (ikkalasi ham bitta massivga qaraydi)

2. Massivni funksiyaga qiymat bo'yicha, massivga ko'rsatkich (*[5]int) bo'yicha va slice sifatida uzatuvchi uchta funksiya yozing. Har birida birinchi elementni o'zgartirib, chaqiruvchi tomonda qaysi holatda o'zgarish ko'rinishini aniqlang.
Misol: [5]int{1, 2, 3, 4, 5}, birinchi element 100 ga o'zgartirilsa → qiymat bo'yicha: [1 2 3 4 5] (o'zgarmaydi); ko'rsatkich bo'yicha: [100 2 3 4 5]; slice: [100 2 3 4 5]

3. make([]int, 3, 10) bilan slice yarating va uning len va cap qiymatlarini chiqaring. So'ng unga 8 ta element qo'shib, har bir append dan keyin len va cap ni chiqaring.
Misol: make([]int, 3, 10) → len = 3, cap = 10; 8 ta append dan keyin len:cap = 4:10 5:10 6:10 7:10 8:10 9:10 10:10 11:20

4. Bo'sh slice'ga 1 dan 2000 gacha sonlarni append bilan qo'shing. cap o'zgargan har bir momentni (eski va yangi sig'im) chiqarib, sig'im qanday o'sishini kuzating.
Misol: 1…2000 ni qo'shganda sig'im o'zgargan momentlar (Go versiyasiga qarab biroz farq qilishi mumkin): 4 8 16 32 64 128 256 512 848 1280 1792 2560

5. nil slice (var s []int) va bo'sh slice (s := []int{}) ni solishtiring: len, cap, s == nil natijalarini chiqaring hamda ikkalasiga ham append va for range ishlashini ko'rsating.
Misol: var s []int → len = 0, cap = 0, s == nil → true; s := []int{} → 0 0 false; ikkalasiga append(s, 1) → [1]

Qism slice va umumiy xotira

6. a := []int{1, 2, 3, 4, 5} va b := a[1:3] berilgan. b[0] ni o'zgartiring va a ga ta'sirini ko'rsating. b ning len va cap qiymatlarini tushuntiring.
Misol: a := []int{1, 2, 3, 4, 5}, b := a[1:3], b[0] = 20 → a = [1 20 3 4 5]; len(b) = 2, cap(b) = 4

7. b := a[1:3] qism slice'ga append(b, 100) qiling va a massivining o'zgarganini ko'rsating. So'ng uch indeksli ifoda a[1:3:3] yordamida bu muammoning oldini oling.
Misol: append(b, 100) → a = [1 2 3 100 5]; b := a[1:3:3] bilan append(b, 100) → a = [1 2 3 4 5], b = [2 3 100]

8. Slice berilgan. Uning mustaqil nusxasini copy yordamida va append([]int(nil), s...) yordamida yarating. Nusxani o'zgartirib, asl slice o'zgarmaganini tekshiring.
Misol: s = [1 2 3], nusxaning birinchi elementi 99 ga o'zgartirilsa → nusxa [99 2 3], asl [1 2 3]

9. Katta slice'ning (1 000 000 element) dastlabki 10 ta elementini qaytaruvchi funksiya yozing: a) s[:10] qaytarib; b) nusxa olib qaytarib. Nega b) variant xotira nuqtai nazaridan to'g'riroq ekanini izohlang.
Misol: a) s[:10] → len = 10, cap = 1000000 (butun massiv xotirada qoladi); b) nusxa → len = 10, cap = 10

10. copy(dst, src) funksiyasining qaytaradigan qiymatini tekshiring: dst qisqa, src qisqa va ular bir xotirada ustma-ust tushgan (masalan copy(s[1:], s)) hollarni sinab ko'ring.
Misol: copy(dst[:2], src[:5]) → 2; s := []int{1, 2, 3, 4, 5}; copy(s[1:], s) → 4, s = [1 1 2 3 4]

Slice ustida amallar

11. Slice va i indeksi berilgan. i-elementni o'chiruvchi ikkita funksiya yozing: tartibni saqlaydigan (append(s[:i], s[i+1:]...)) va tartibni saqlamaydigan, lekin tezroq (oxirgi element bilan almashtirish).
Misol: [1 2 3 4 5], i = 1 → tartibni saqlaydigan [1 3 4 5]; saqlamaydigan [1 5 3 4]

12. Slice, i indeksi va x qiymati berilgan. x ni i-o'ringa qo'shuvchi funksiya yozing (slices.Insert ishlatmasdan), so'ng natijani slices.Insert bilan solishtiring.
Misol: [1 2 4], i = 2, x = 3 → [1 2 3 4]

13. Butun sonlar slice'idan juft sonlarni yangi xotira ajratmasdan (joyida, s[:0] usuli bilan) filtrlovchi funksiya yozing.
Misol: [1 2 3 4 5 6] → [2 4 6]

14. Slice'ni joyida teskari tartibga o'tkazuvchi funksiya yozing va natijani slices.Reverse bilan solishtiring.
Misol: [1 2 3] → [3 2 1]

15. slices paketidagi Contains, Index, Max, Min, Sort, BinarySearch, Compact va Equal funksiyalaridan foydalanib, bitta slice ustida bir necha amalni bajaruvchi dastur tuzing.
Misol: s = [3 1 2 2 5]: Contains(s, 2) → true; Index(s, 5) → 4; Max → 5; Min → 1; Sort → [1 2 2 3 5]; BinarySearch(s, 3) → 3 true; Compact → [1 2 3 5]

Ko'p o'lchamli slice'lar va amaliy masalalar

16. N×M o'lchamli ikki o'lchamli slice ([][]int) yarating: a) har bir qator uchun alohida make; b) bitta make([]int, N*M) dan qatorlarni kesib olish orqali. Ikkala usulni solishtiring.
Misol: N = 2, M = 3 → [[0 0 0] [0 0 0]] (ikkala usulda ham bir xil; b) usulda barcha qatorlar bitta massivni bo'lishadi)

17. «Uchburchak» ko'rinishidagi slice yarating: i-qatorda i+1 ta element bo'lsin va unga Paskal uchburchagining dastlabki N qatorini yozing.
Misol: N = 5 → [[1] [1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1]]

18. Stekni []int slice asosida amalga oshiring: Push, Pop, Peek, Len. Pop dan keyin xotira oqib ketmasligi uchun nima qilish kerakligini izohlang (ko'rsatkichli elementlar misolida).
Misol: Push(1), Push(2), Peek() → 2, Pop() → 2, Len() → 1

19. Navbatni slice asosida amalga oshiring va 1 000 000 ta Push/Pop dan keyin ichki massiv hajmi cheksiz o'sib ketmasligini ta'minlang.
Misol: 1000000 ta Push/Pop dan keyin Len() = 0, ichki massiv sig'imi esa kichik (masalan cap ≤ 1024) bo'lib qoladi

20. Slice'ni n tadan elementli bo'laklarga (chunk) bo'luvchi funksiya yozing: Chunk([]int{1,2,3,4,5}, 2) → [[1 2] [3 4] [5]]. Bo'laklar asl slice bilan xotirani bo'lishmasligi kerak.
Misol: Chunk([]int{1, 2, 3, 4, 5}, 2) → [[1 2] [3 4] [5]]