Wprowadzenie

W tym raporcie skupimy się na temacie Bootstrapingu. Z definicji (pol.metody samowsporne) bootstraping został wprowadzony przez Bradleya Efrona jako metoda szacowania rozkładu błędów estymacji, za pomocą wielokrotnego losowania ze zwracaniem z próby.

Metoda bootstrap jest też używana do weryfikacji hipotez statystycznych, o ile da się tę weryfikację sprowadzić do badania błędu estymacji za pomocą statystyki spełniającej warunki bootstrapu.

Kolejnym elementem będzie przedstawienie przykładowej analizy bootstrap

Zadanie 1

Zadanie 1. Estymacja błędu standardowego średniej próbkowej metodą bootstrap.

Załóżmy, że chcemy badać populację o rozkładzie normalnym ze średnią 3 i odchyleniem standardowym 1. i)Wygeneruj przykładową populację liczności 25 o takim rozkładzie (funkcja rnorm()). ii)Wygeneruj 1000 prób o liczności 25 z otrzymanych danych (funkcja replicate()). iii)Oblicz średnią każdej z 1000 wylosowanych prób bootstrapowych oraz przedstaw histogram rozkładu tych średnich. Porównaj ten rozkład z rozkładem cechy (rozkładem normalnym N (3;1)). Oceń, czy przybliżenie rozkładu metodą bootstrap jest adekwatne (czy kształty obu rozkładów są podobne) iv)Porównaj średnią wygenerowanej próby wyjściowej ze średnią wektora średnich z prób bootstrapowych. Oceń ich różnicę. v)Przy użyciu funkcji boot (pakiet boot) wyznacz błąd standardowy dla średniej.

Wyznaczono populacje o liczności 25 i rozkładzie normalnym o podanych wartościach średniej i odchylenia. Następnie dokonano 1000 replikacji bootstrapowych dla próby i obliczono dla każdej próby średnią. Wykonano histogram dla tych średnich oraz dla rozkładu normalnego o podanych wartościach.

Analiza wzrokowa wskazuje, że rozkłady te są podobne. Jednak, nie moża stwierdzić, że przybliżenie rozkładu metodą bootstrap jest adekwatne, gdyż pojawiają się nieobserwowalne w rozkładzie boostrapowym wzniesiania na ogonach w rozkładzie normalnym.

Następnym krokiem jest oszacowanie średniej dla zbioru bootstrapowego oraz zbioru o rozkładzie normalnym

## [1] 2.99395
## [1] 3.09508

Porównując średnią z rozkładu oraz bootstrapową, widać nieznaczne różnice. Warto jednak zaznaczyć, że nie jest ona zbyt istotna.

Następnym elementem jest wyznaczenie błedu standardowego dla średniej bootstrapowej.

## 
## ORDINARY NONPARAMETRIC BOOTSTRAP
## 
## 
## Call:
## boot(data = normal, statistic = function(d, w) sum(w * d), R = 1000, 
##     stype = "w")
## 
## 
## Bootstrap Statistics :
##     original       bias    std. error
## t1*  3.09508 0.0003354374   0.1901956

Błąd standardowy jest równy wartość stojącą przy “std.error”

Zadanie 2

Zadanie 2. Estymacja przedziałowa średniej metodą bootstrap.

i)Wygeneruj próbkę losową 50 obserwacji wybranej zmiennej z pliku dane.sav (funkcja sample()). Jako populację potraktuj cały zbiór N-obserwacji w pliku. ii)Oszacuj przedziałowo (klasycznie – stosując aproksymację rozkładem normalnym) oraz nieklasycznie (stosując funkcję boot.ci()) średnią wybranej zmiennej w próbce. Oblicz oraz porównaj oba błędy standardowe (względny %) estymacji przedziałowej klasycznej i nieklasycznej. Podaj wnioski.

Wybieramy losowo 50 obserwacji ze zbioru danych. Do analizy wzięto dane ze zbioru zmiennej Calkowite_wydatki_GD_GUS. Następnie będziemy szacować przedziały ufności.

Srednia oraz odchylenie standardowe zbioru przedstawia się:

## [1] 2199.601
## [1] 2188.643

Obliczono wpierw klasyczne przedział jednego odchylenia standardowego od średniej dla próbki metodą klasyczną.

## [1] 1592.94
## [1] 2806.262

Następnie stworzono przedział ufności 95% oraz 5% metodą klasyczną dla rozkładu normalnego o średniej równej 1

## [1] 1577.595 2821.606
## attr(,"conf.level")
## [1] 0.95

Powyższej analizy dokonano także metodą boostrapową:

Średnia oraz odchylenie standardowe kształtowało się następująco:

## [1] 2169.06
## [1] 314.0483

Obiczono przedziały dla jednego odchylenia standardowego.

##         dolny    gorny
## [1,] 1562.399 2775.721

Następnie stworzono przedział ufności 95% oraz 5%.

##      95% 
## 2671.134
##      5% 
## 1667.64

Alternatywnie, powyższych analiz można dokonać poprzez funkcję boot.ci

## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 50 bootstrap replicates
## 
## CALL : 
## boot.ci(boot.out = boot(dochod, function(d, w) sum(w * d), R = 50, 
##     stype = "w"), conf = c(0.05, 0.95), type = c("norm", "perc"))
## 
## Intervals : 
## Level      Normal             Percentile     
## 5%   (2229, 2262 )   (2126, 2148 )   
## 95%   (1737, 2754 )   (1647, 2788 )  
## Calculations and Intervals on Original Scale
## Some percentile intervals may be unstable

Na koniec dokonano analizy błędów standardowych dla estymowanych zmiennych

Dla rozkładu normalnego wynosi on:

## [1] 0.1407169

Natomiast dla bootstrapa:

## [1] 0.02000665

Wnioski

Widoczna jest więc znaczna różnica w estymacji, gdyż błędy standardowe są inne. Jednak w przypadku bootstrapa, błąd ten jest zawsze niższy.

LS0tCnRpdGxlOiAnTmlla2xhc3ljem5lIG1ldG9keSBzdGF0eXN0eWtpJwpzdWJ0aXRsZTogJ0Jvb3RzdHJhcCcKZGF0ZTogImByIFN5cy5EYXRlKClgIgphdXRob3I6ICJNYWNpZWogSG9yaXN6bnkiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiAKICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQogICAgZm9udHNpemU6IDEwcHQKICAgIHRvYzogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBubwogICAgZGZfcHJpbnQ6IGRlZmF1bHQKICAgIHRvY19kZXB0aDogNQplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSkKbGlicmFyeShib290KQoKYGBgCgojIFdwcm93YWR6ZW5pZQoKVyB0eW0gcmFwb3JjaWUgc2t1cGlteSBzacSZIG5hIHRlbWFjaWUgKkJvb3RzdHJhcGluZ3UqLiBaIGRlZmluaWNqaSAocG9sLm1ldG9keSBzYW1vd3Nwb3JuZSkgYm9vdHN0cmFwaW5nIHpvc3RhxYIgd3Byb3dhZHpvbnkgcHJ6ZXogQnJhZGxleWEgRWZyb25hIGpha28gbWV0b2RhIHN6YWNvd2FuaWEgcm96a8WCYWR1IGLFgsSZZMOzdyBlc3R5bWFjamksIHphIHBvbW9jxIUgd2llbG9rcm90bmVnbyBsb3Nvd2FuaWEgemUgendyYWNhbmllbSB6IHByw7NieS4KCk1ldG9kYSBib290c3RyYXAgamVzdCB0ZcW8IHXFvHl3YW5hIGRvIHdlcnlmaWthY2ppIGhpcG90ZXogc3RhdHlzdHljem55Y2gsIG8gaWxlIGRhIHNpxJkgdMSZIHdlcnlmaWthY2rEmSBzcHJvd2FkemnEhyBkbyBiYWRhbmlhIGLFgsSZZHUgZXN0eW1hY2ppIHphIHBvbW9jxIUgc3RhdHlzdHlraSBzcGXFgm5pYWrEhWNlaiB3YXJ1bmtpIGJvb3RzdHJhcHUuCgpLb2xlam55bSBlbGVtZW50ZW0gYsSZZHppZSBwcnplZHN0YXdpZW5pZSBwcnp5a8WCYWRvd2VqIGFuYWxpenkgYm9vdHN0cmFwCgojIyBaYWRhbmllIDEKClphZGFuaWUgMS4gRXN0eW1hY2phIGLFgsSZZHUgc3RhbmRhcmRvd2VnbyDFm3JlZG5pZWogcHLDs2Jrb3dlaiBtZXRvZMSFIGJvb3RzdHJhcC4KClphxYLDs8W8bXksIMW8ZSBjaGNlbXkgYmFkYcSHIHBvcHVsYWNqxJkgbyByb3prxYJhZHppZSBub3JtYWxueW0gemUgxZtyZWRuacSFIDMgaSBvZGNoeWxlbmllbSBzdGFuZGFyZG93eW0gMS4KaSlXeWdlbmVydWogcHJ6eWvFgmFkb3fEhSBwb3B1bGFjasSZIGxpY3pub8WbY2kgMjUgbyB0YWtpbSByb3prxYJhZHppZSAoZnVua2NqYSBybm9ybSgpKS4KaWkpV3lnZW5lcnVqIDEwMDAgcHLDs2IgbyBsaWN6bm/Fm2NpIDI1IHogb3RyenltYW55Y2ggZGFueWNoIChmdW5rY2phIHJlcGxpY2F0ZSgpKS4KaWlpKU9ibGljeiDFm3JlZG5pxIUga2HFvGRlaiB6IDEwMDAgd3lsb3Nvd2FueWNoIHByw7NiIGJvb3RzdHJhcG93eWNoIG9yYXogcHJ6ZWRzdGF3IGhpc3RvZ3JhbSByb3prxYJhZHUgdHljaCDFm3JlZG5pY2guIFBvcsOzd25haiB0ZW4gcm96a8WCYWQgeiByb3prxYJhZGVtIGNlY2h5IChyb3prxYJhZGVtIG5vcm1hbG55bSBOICgzOzEpKS4gT2NlxYQsIGN6eSBwcnp5YmxpxbxlbmllIHJvemvFgmFkdSBtZXRvZMSFIGJvb3RzdHJhcCBqZXN0IGFkZWt3YXRuZSAoY3p5IGtzenRhxYJ0eSBvYnUgcm96a8WCYWTDs3cgc8SFIHBvZG9ibmUpCml2KVBvcsOzd25haiDFm3JlZG5pxIUgd3lnZW5lcm93YW5laiBwcsOzYnkgd3lqxZtjaW93ZWogemUgxZtyZWRuacSFIHdla3RvcmEgxZtyZWRuaWNoIHogcHLDs2IgYm9vdHN0cmFwb3d5Y2guIE9jZcWEIGljaCByw7PFvG5pY8SZLgp2KVByenkgdcW8eWNpdSBmdW5rY2ppIGJvb3QgKHBha2lldCBib290KSB3eXpuYWN6IGLFgsSFZCBzdGFuZGFyZG93eSBkbGEgxZtyZWRuaWVqLgoKPj5XeXpuYWN6b25vIHBvcHVsYWNqZSBvIGxpY3pub8WbY2kgMjUgaSByb3prxYJhZHppZSBub3JtYWxueW0gbyBwb2RhbnljaCB3YXJ0b8WbY2lhY2ggxZtyZWRuaWVqIGkgb2RjaHlsZW5pYS4gTmFzdMSZcG5pZSBkb2tvbmFubyAxMDAwIHJlcGxpa2FjamkgYm9vdHN0cmFwb3d5Y2ggZGxhIHByw7NieSBpIG9ibGljem9ubyBkbGEga2HFvGRlaiBwcsOzYnkgxZtyZWRuacSFLiBXeWtvbmFubyBoaXN0b2dyYW0gZGxhIHR5Y2ggxZtyZWRuaWNoIG9yYXogZGxhIHJvemvFgmFkdSBub3JtYWxuZWdvIG8gcG9kYW55Y2ggd2FydG/Fm2NpYWNoLiAKCmBgYHtyIGNhcnN9Cgpub3JtYWw8LShybm9ybSgyNSwzLDEpKQpkYXRhPC0gcmVwbGljYXRlKDEwMDAscm5vcm0oMjUsMywxKSkKbm9icz1sZW5ndGgoZGF0YSkKZm9yIChpIGluIDE6MTAwMCkgCnsKICBib290LmRhdGE9c2FtcGxlKGRhdGEsbm9icyxyZXBsYWNlPVRSVUUpCiAgZGF0YVtpXT1tZWFuKGJvb3QuZGF0YSkKfQpgYGAKCmBgYHtyIG5vcm19CnBsb3QoZGVuc2l0eShub3JtYWwpLCBtYWluID0gIlJvemvFgmFkIG5vcm1hbG55IikgCgpgYGAKCmBgYHtyIGJvb3Rvd3l9CnBsb3QoZGVuc2l0eShib290LmRhdGEpLCBtYWluID0gIlJvemvFgmFkIGJvb3RzdHJhcG93eSIpCiAgCmBgYAoKCj4+QW5hbGl6YSB3enJva293YSB3c2thenVqZSwgxbxlIHJvemvFgmFkeSB0ZSBzxIUgcG9kb2JuZS4gKipKZWRuYWsqKiwgbmllIG1vxbxhIHN0d2llcmR6acSHLCDFvGUgcHJ6eWJsacW8ZW5pZSByb3prxYJhZHUgbWV0b2TEhSBib290c3RyYXAgamVzdCBhZGVrd2F0bmUsIGdkecW8IHBvamF3aWFqxIUgc2nEmSBuaWVvYnNlcndvd2FsbmUgdyByb3prxYJhZHppZSBib29zdHJhcG93eW0gd3puaWVzaWFuaWEgbmEgb2dvbmFjaCB3IHJvemvFgmFkemllIG5vcm1hbG55bS4KCk5hc3TEmXBueW0ga3Jva2llbSBqZXN0IG9zemFjb3dhbmllIMWbcmVkbmllaiBkbGEgemJpb3J1IGJvb3RzdHJhcG93ZWdvIG9yYXogemJpb3J1IG8gcm96a8WCYWR6aWUgbm9ybWFsbnltCgpgYGB7ciBwcmVzc3VyZSwgZWNobz1GQUxTRSwgcmVzdWx0cz1GfQpzZTI8LXNkKGJvb3QuZGF0YSkvc3FydChsZW5ndGgoYm9vdC5kYXRhKSkKc2UyCgpzZXAyPC1zZTIvbWVhbihib290LmRhdGEpCnNlcDIKYGBgCgoKCmBgYHtyIHNyZWRuaWFhYX0KbWVhbihib290LmRhdGEpCm1lYW4obm9ybWFsKQpgYGAKCj4+UG9yw7N3bnVqxIVjIMWbcmVkbmnEhSB6IHJvemvFgmFkdSBvcmF6IGJvb3RzdHJhcG93xIUsIHdpZGHEhyBuaWV6bmFjem5lIHLDs8W8bmljZS4gV2FydG8gamVkbmFrIHphem5hY3p5xIcsIMW8ZSBuaWUgamVzdCBvbmEgemJ5dCBpc3RvdG5hLgoKTmFzdMSZcG55bSBlbGVtZW50ZW0gamVzdCB3eXpuYWN6ZW5pZSBixYJlZHUgc3RhbmRhcmRvd2VnbyBkbGEgxZtyZWRuaWVqIGJvb3RzdHJhcG93ZWouCmBgYHtyIGJsYXN9CmJvb3Qobm9ybWFsLCBmdW5jdGlvbihkLCB3KSBzdW0odyAqIGQpLApSPTEwMDAsIHN0eXBlPSJ3IikKYGBgCgo+PiBCxYLEhWQgc3RhbmRhcmRvd3kgamVzdCByw7N3bnkgd2FydG/Fm8SHIHN0b2rEhWPEhSBwcnp5ICJzdGQuZXJyb3IiCgojIyBaYWRhbmllIDIKClphZGFuaWUgMi4gRXN0eW1hY2phIHByemVkemlhxYJvd2EgxZtyZWRuaWVqIG1ldG9kxIUgYm9vdHN0cmFwLgoKaSlXeWdlbmVydWogcHLDs2JrxJkgbG9zb3fEhSA1MCBvYnNlcndhY2ppIHd5YnJhbmVqIHptaWVubmVqIHogcGxpa3UgZGFuZS5zYXYgKGZ1bmtjamEgc2FtcGxlKCkpLiBKYWtvIHBvcHVsYWNqxJkgcG90cmFrdHVqIGNhxYJ5IHpiacOzciBOLW9ic2Vyd2FjamkgdyBwbGlrdS4KaWkpT3N6YWN1aiBwcnplZHppYcWCb3dvIChrbGFzeWN6bmllIOKAkyBzdG9zdWrEhWMgYXByb2tzeW1hY2rEmSByb3prxYJhZGVtIG5vcm1hbG55bSkgb3JheiBuaWVrbGFzeWN6bmllIChzdG9zdWrEhWMgZnVua2NqxJkgYm9vdC5jaSgpKSDFm3JlZG5pxIUgd3licmFuZWogem1pZW5uZWogdyBwcsOzYmNlLiBPYmxpY3ogb3JheiBwb3LDs3duYWogb2JhIGLFgsSZZHkgc3RhbmRhcmRvd2UgKHd6Z2zEmWRueSAlKSBlc3R5bWFjamkgcHJ6ZWR6aWHFgm93ZWoga2xhc3ljem5laiBpIG5pZWtsYXN5Y3puZWouIFBvZGFqIHduaW9za2kuIAoKCmBgYHtyIGRydWdpZSwgd2FybmluZz1GLCByZXN1bHRzPUZ9CmdldHdkKCkKc2V0d2QoIi9Vc2Vycy9rcm9sbWFjaXVzaS9Eb3dubG9hZHMiKQpsaWJyYXJ5KGhhdmVuKQpkYXRhPC1yZWFkX3NhdigiZGFuZS5zYXYiKQpgYGAKCj4+V3liaWVyYW15IGxvc293byA1MCBvYnNlcndhY2ppIHplIHpiaW9ydSBkYW55Y2guIERvIGFuYWxpenkgd3ppxJl0byBkYW5lIHplIHpiaW9ydSB6bWllbm5laiAqQ2Fsa293aXRlX3d5ZGF0a2lfR0RfR1VTKi4gIE5hc3TEmXBuaWUgYsSZZHppZW15IHN6YWNvd2HEhyBwcnplZHppYcWCeSB1Zm5vxZtjaS4gCgpgYGB7ciBkYW5lLCB3YXJuaW5nPUYsIHJlc3VsdHM9Rn0KCmF0dGFjaChkYXRhKQpkb2Nob2Q8LXNhbXBsZShDYWxrb3dpdGVfd3lkYXRraV9HRF9HVVMsNTApCgojcHVua3Rvd28ga2xhc3ljem5pZQptZWFuKGRvY2hvZCkKc2QoZG9jaG9kKQpgYGAKCj4+IFNyZWRuaWEgb3JheiBvZGNoeWxlbmllIHN0YW5kYXJkb3dlIHpiaW9ydSBwcnplZHN0YXdpYSBzacSZOgoKYGBge3IgemJpb3J9Cm1lYW4oZG9jaG9kKQpzZChkb2Nob2QpCnNlPC1zZChkb2Nob2QpL3NxcnQobGVuZ3RoKGRvY2hvZCkpCmBgYAoKPj4gT2JsaWN6b25vIHdwaWVydyBrbGFzeWN6bmUgcHJ6ZWR6aWHFgiBqZWRuZWdvIG9kY2h5bGVuaWEgc3RhbmRhcmRvd2VnbyBvZCDFm3JlZG5pZWogZGxhIHByw7Nia2kgbWV0b2TEhSBrbGFzeWN6bsSFLgoKYGBge3Iga2xhc30KCiNwcnplZHppYeKJpW93byBrbGFzeWN6bmllCm1lYW4oZG9jaG9kKS0xLjk2KnNlICAgCm1lYW4oZG9jaG9kKSsxLjk2KnNlICAgCgpgYGAKCj4+IE5hc3TEmXBuaWUgc3R3b3J6b25vIHByemVkemlhxYIgdWZub8WbY2kgOTUlIG9yYXogNSUgbWV0b2TEhSBrbGFzeWN6bsSFIGRsYSByb3prxYJhZHUgbm9ybWFsbmVnbyBvIMWbcmVkbmllaiByw7N3bmVqIDEKCmBgYHtyIG5vcn0KdC50ZXN0KGRvY2hvZCkkY29uZi5pbnQKYGBgCgpQb3d5xbxzemVqIGFuYWxpenkgZG9rb25hbm8gdGFrxbxlIG1ldG9kxIUgYm9vc3RyYXBvd8SFOgoKYGBge3IgYm90fQoKQj01MAptZWFuLmRvY2hvZD1yZXAoMCxCKQpub2JzPWxlbmd0aChkb2Nob2QpIAoKIGZvciAoaSBpbiAxOkIpIAp7CiBib290LmRhdGE9c2FtcGxlKGRvY2hvZCxub2JzLHJlcGxhY2U9VFJVRSkKIG1lYW4uZG9jaG9kW2ldPW1lYW4oYm9vdC5kYXRhKQogfQoKYGBgCgo+PiDFmnJlZG5pYSBvcmF6IG9kY2h5bGVuaWUgc3RhbmRhcmRvd2Uga3N6dGHFgnRvd2HFgm8gc2nEmSBuYXN0xJlwdWrEhWNvOgoKYGBge3Igc3JlZG5pYX0KbWVhbihtZWFuLmRvY2hvZCkKCnNkKG1lYW4uZG9jaG9kKQpgYGAKCj4+IE9iaWN6b25vIHByemVkemlhxYJ5IGRsYSBqZWRuZWdvIG9kY2h5bGVuaWEgc3RhbmRhcmRvd2Vnby4KCmBgYHtyIGJvc3R9CmRvbG55PC1tZWFuKG1lYW4uZG9jaG9kKS0xLjk2KnNlCmdvcm55PC1tZWFuKG1lYW4uZG9jaG9kKSsxLjk2KnNlCmNiaW5kKGRvbG55LGdvcm55KQoKYGBgCgo+PiBOYXN0xJlwbmllIHN0d29yem9ubyBwcnplZHppYcWCIHVmbm/Fm2NpIDk1JSBvcmF6IDUlLgoKYGBge3IgYm9vdHN9CgpxdWFudGlsZShtZWFuLmRvY2hvZCwwLjk1KQpxdWFudGlsZShtZWFuLmRvY2hvZCwwLjA1KQoKYGBgCgpBbHRlcm5hdHl3bmllLCBwb3d5xbxzenljaCBhbmFsaXogbW/FvG5hIGRva29uYcSHIHBvcHJ6ZXogZnVua2NqxJkgYm9vdC5jaQoKYGBgIHtyIGlubmV9Cgpib290LmNpKGJvb3QoZG9jaG9kLCBmdW5jdGlvbihkLCB3KSBzdW0odyAqIGQpLAogICAgICAgICAgICAgUj01MCwgc3R5cGU9InciKSwgY29uZj1jKDAuMDUsMC45NSksIHR5cGU9YygKICAgICAgICAgICAgICAgIm5vcm0iLCJwZXJjIikpCmBgYAoKYGBgIHtyIGtvbGVqbnkgYm9vdH0KbWVhbi5ib290PWZ1bmN0aW9uKGRvY2hvZCxpZHgpIHsKYW5zPW1lYW4oZG9jaG9kW2lkeF0pCmFucwp9CgpET0NIT0QubWVhbi5ib290ID0gYm9vdChkb2Nob2Qsc3RhdGlzdGljPW1lYW4uYm9vdCwgUj01MCkKCmBgYAoKYGBge3IgcGxvdH0KcGxvdChET0NIT0QubWVhbi5ib290LCBtYWluPU5VTEwpCmBgYAoKTmEga29uaWVjIGRva29uYW5vIGFuYWxpenkgYsWCxJlkw7N3IHN0YW5kYXJkb3d5Y2ggZGxhIGVzdHltb3dhbnljaCB6bWllbm55Y2gKCj4+IERsYSByb3prxYJhZHUgbm9ybWFsbmVnbyB3eW5vc2kgb246CgpgYGB7ciBub3JtYWxueX0Kc2U8LXNkKGRvY2hvZCkvc3FydChsZW5ndGgoZG9jaG9kKSkKc2VwPC1zZS9tZWFuKGRvY2hvZCkKc2VwCmBgYAoKCj4+IE5hdG9taWFzdCBkbGEgYm9vdHN0cmFwYToKCmBgYHtyIHN0eXBlfQpsb29wPC1ib290KGRvY2hvZCwgZnVuY3Rpb24oZCwgdykgc3VtKHcgKiBkKSwKICAgICAgICAgICAgIFI9NTAsIHN0eXBlPSJ3IikKCnNlPC1zZChsb29wJHQpL3NxcnQobGVuZ3RoKGxvb3AkdCkpCnNlcDwtc2UvbWVhbihsb29wJHQpCnNlcApgYGAKCgojIFduaW9za2kKCldpZG9jem5hIGplc3Qgd2nEmWMgem5hY3puYSByw7PFvG5pY2EgdyBlc3R5bWFjamksIGdkecW8IGLFgsSZZHkgc3RhbmRhcmRvd2Ugc8SFIGlubmUuICoqSmVkbmFrKiogdyBwcnp5cGFka3UgYm9vdHN0cmFwYSwgYsWCxIVkIHRlbiBqZXN0IHphd3N6ZSBuacW8c3p5Lgo=