diff --git a/exercises/practice/bob/.articles/performance/code/.gitignore b/exercises/practice/bob/.articles/performance/code/.gitignore new file mode 100644 index 000000000..b8cfc22e2 --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/.gitignore @@ -0,0 +1,4 @@ +/target +Cargo.lock + +/results \ No newline at end of file diff --git a/exercises/practice/bob/.articles/performance/code/Cargo.toml b/exercises/practice/bob/.articles/performance/code/Cargo.toml new file mode 100644 index 000000000..4173bf139 --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "bob_reply" +version = "0.1.0" +edition = "2024" + +[dependencies] + + +[dev-dependencies] +criterion = "0.5.1" + +[[bench]] +name = "bob_benchmark" +harness = false diff --git a/exercises/practice/bob/.articles/performance/code/benches/10000_lorem_ipsum.txt b/exercises/practice/bob/.articles/performance/code/benches/10000_lorem_ipsum.txt new file mode 100644 index 000000000..91ec148ce --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/benches/10000_lorem_ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas mattis congue dolor at consequat. In id fermentum arcu, nec elementum tortor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce libero dolor, accumsan ac mollis eu, gravida at elit. Nulla cursus, lacus nec varius fermentum, ex ex hendrerit urna, ut ultrices justo diam vitae massa. Aliquam erat volutpat. Nullam maximus pretium felis, vestibulum blandit arcu lacinia nec. In accumsan ultrices urna.Nunc gravida interdum nulla fermentum vestibulum. Pellentesque varius sed mi a hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed ipsum sapien. Nullam ut pharetra dui, et porttitor urna. Sed id arcu sagittis, venenatis ipsum a, tristique orci. Phasellus condimentum metus velit, id fermentum purus mattis ut. Morbi facilisis accumsan pretium. Aenean id mollis urna.Morbi imperdiet at lacus molestie tempor. Donec neque magna, placerat eget lorem sed, scelerisque bibendum leo. Maecenas aliquet risus dictum pharetra vehicula. Maecenas vitae quam sed ligula egestas fermentum sagittis sed tellus. Aenean eget sodales nisl. Nulla vitae arcu turpis. Duis consequat leo at finibus eleifend. Vestibulum pellentesque lacinia diam quis laoreet. Phasellus dapibus, sem eu mattis cursus, ex mi ornare orci, in lacinia arcu turpis sed sapien. Sed fermentum ante enim, id ultricies sem volutpat a. Etiam mollis odio et massa luctus tincidunt. Integer sagittis diam non venenatis ultrices. Quisque non maximus eros, ut tristique nisl. Nunc congue nisl cursus turpis tempor ornare. Vivamus vehicula mollis iaculis. Vivamus mi nisi, posuere ac est a, porttitor aliquam nulla.Sed in lorem sit amet risus feugiat hendrerit. Donec dictum euismod lorem eget viverra. Phasellus vitae erat sapien. In hac habitasse platea dictumst. Integer malesuada rhoncus fermentum. Nulla quis dignissim dolor. Morbi quis lacus sed tortor faucibus porta. Nam dignissim egestas mi. Maecenas dignissim, nisl pulvinar elementum pellentesque, justo tortor dapibus lacus, nec cursus odio metus nec odio. Suspendisse potenti. Aliquam sit amet ligula justo. Sed varius lobortis diam.Fusce sed pretium mi. Pellentesque in ullamcorper enim, eu mollis tortor. Quisque in odio nisi. Phasellus consectetur fermentum sapien, non lobortis mauris vestibulum sit amet. Praesent sed ornare nulla, vitae porta mauris. Nunc vulputate accumsan scelerisque. Donec nec condimentum lacus, quis mollis neque. Phasellus iaculis at arcu nec pulvinar. Nam accumsan rutrum erat id sollicitudin. Nam quis lectus in diam efficitur fermentum ut a lorem. Nulla tempor vitae magna vel rutrum. In nec luctus dolor. Aenean malesuada sollicitudin arcu a dapibus. Morbi elementum metus non magna varius congue.Phasellus nibh risus, imperdiet sed semper sed, pharetra viverra velit. Aliquam libero erat, tempor fringilla urna eu, semper dignissim purus. Aliquam id lorem a arcu semper ultrices ut vel felis. Cras sit amet urna id erat aliquet varius. Morbi malesuada sodales elit, vitae porta odio vulputate nec. Duis volutpat quis felis et consectetur. Morbi justo libero, pulvinar eget mauris eget, tristique volutpat dolor. Sed vulputate urna sit amet est ultrices, quis molestie sapien dapibus. Phasellus vehicula ligula eu turpis venenatis porta. Ut mi dolor, euismod sed odio quis, volutpat facilisis lectus. Quisque sem lacus, faucibus nec enim vitae, tristique malesuada magna. Donec elit elit, congue mollis magna at, posuere tempor tortor.Etiam varius maximus efficitur. Praesent bibendum eros sit amet eros luctus, nec facilisis nisl hendrerit. Nulla facilisi. Maecenas dapibus, tellus vitae ultricies condimentum, ipsum libero lacinia eros, eget mattis diam diam eu elit. Maecenas cursus tincidunt feugiat. Sed efficitur erat enim. In viverra lacinia ex, eget viverra mi aliquam in. Vestibulum id ultrices justo. Pellentesque fringilla pellentesque ligula eget egestas. Morbi iaculis vel purus ac tempor. In volutpat sem id tincidunt feugiat.Nullam eu felis commodo, viverra erat et, dapibus leo. Nulla bibendum, nibh eget congue facilisis, urna massa tristique turpis, at finibus velit ex eu tortor. Pellentesque finibus lobortis dolor, eget pretium massa tristique in. Donec venenatis facilisis efficitur. Integer quis metus vitae nisl tincidunt pulvinar eu id nisl. Sed viverra ipsum a mollis rhoncus. Mauris auctor sed justo non tempor. Vivamus commodo urna sit amet hendrerit bibendum. Phasellus id nibh ante.Suspendisse felis est, condimentum eget venenatis nec, eleifend vel sapien. Ut posuere luctus diam, eu molestie urna semper et. Duis dolor elit, elementum auctor elit eget, porttitor sodales dui. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam in aliquet metus. Cras vel odio vel est tristique vehicula quis non augue. Quisque condimentum ipsum varius diam iaculis tincidunt. Integer luctus, magna quis aliquet pretium, augue felis cursus metus, sit amet iaculis sapien quam at massa.Mauris condimentum ipsum ullamcorper ex tempus, nec tristique ante ullamcorper. Sed consectetur augue id eros posuere hendrerit. Phasellus euismod dapibus lectus. Etiam lobortis sollicitudin turpis, quis aliquam sem lacinia congue. Nunc aliquam feugiat nisi a aliquet. Vivamus tristique blandit dolor ut consectetur. Aliquam nec enim elit. Pellentesque commodo quis elit vitae cursus. Aenean facilisis pulvinar rhoncus. Proin ultricies et libero eget porta.Maecenas convallis venenatis velit ut aliquet. Ut venenatis hendrerit leo vitae blandit. Nulla convallis eros quis metus condimentum accumsan. Phasellus consequat eu justo et suscipit. Cras suscipit congue sagittis. Suspendisse pharetra vitae nisl in tristique. Nunc lectus lacus, lacinia at rhoncus quis, tristique ac arcu. Proin sagittis nisl ut lacinia sodales. Proin ac dapibus mi. Donec sed lacus ut nibh cursus scelerisque et ut nulla. Aliquam suscipit dignissim magna. In venenatis varius felis, vel pharetra lorem venenatis rutrum. Vivamus consectetur diam nec leo mollis, imperdiet aliquet lectus egestas.In augue lacus, suscipit ac nulla in, congue semper quam. Donec bibendum risus ut nibh pulvinar, cursus pharetra dolor volutpat. Fusce eu rutrum eros. Vivamus ultricies, felis at fringilla sagittis, justo eros fringilla orci, id eleifend purus mi ut ipsum. Nunc porttitor justo rutrum placerat pretium. In pretium quis purus id placerat. Nunc dignissim tellus ex, dignissim elementum quam bibendum a. Nulla facilisi. Curabitur laoreet erat odio, vel pretium odio dapibus ut.Aliquam auctor sodales dui nec mollis. Aenean venenatis felis vitae ultricies eleifend. Maecenas vel est turpis. Phasellus libero libero, aliquet a nibh eu, euismod tincidunt nibh. Etiam hendrerit ligula pulvinar viverra laoreet. Integer vel porta augue. Suspendisse iaculis odio eget elit varius, ultrices blandit ex consequat. Vivamus pharetra, urna sit amet dignissim sodales, ante risus dictum nibh, a tincidunt velit nulla in felis.Maecenas id imperdiet mauris. Pellentesque varius orci sem, eget accumsan erat luctus eu. Pellentesque ultricies vehicula nisi, sit amet porta velit auctor eget. Praesent et aliquam neque, non auctor enim. Sed tortor velit, vehicula sit amet pharetra in, cursus non eros. Aenean vitae diam et mauris mattis porta. In vel mi in tellus posuere lobortis. Nulla hendrerit lacus sit amet metus semper accumsan. Praesent quis tortor feugiat sapien fermentum feugiat vitae sit amet eros. Fusce vitae augue sagittis, lacinia arcu tempor, ullamcorper arcu. Ut non tellus eu dui consequat dictum sit amet nec libero. Sed a viverra tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque faucibus scelerisque ex non condimentum.Duis non odio sed purus dictum maximus id vel turpis. Duis at suscipit augue, et molestie velit. In quis dui venenatis, vulputate justo at, condimentum odio. Morbi vulputate, purus vitae iaculis finibus, tellus elit tincidunt felis, eget finibus tellus massa at justo. Nam auctor at dolor at vulputate. Vestibulum dignissim eget diam quis convallis. Donec varius nisi sed dui vestibulum iaculis. Cras vulputate risus ac laoreet porttitor. Maecenas mattis tincidunt arcu, quis eleifend metus lobortis sed. Suspendisse potenti. Phasellus vitae erat eget elit tincidunt scelerisque.Phasellus vitae volutpat sem. Nunc dictum pharetra arcu, at ornare nisi euismod eget. Nam ipsum tellus, varius nec volutpat nec, eleifend at risus. Maecenas ultrices laoreet odio at commodo. Donec aliquam blandit metus, vel efficitur mi. Donec gravida dolor lectus, sit amet interdum tortor semper a. Proin sodales blandit augue elementum aliquam. Nullam lacinia, quam vel sagittis efficitur, augue tellus ornare risus, quis posuere enim sem ut augue. Proin tincidunt sollicitudin accumsan.Sed lobortis, orci id porta fermentum, sem leo sodales neque, non venenatis mauris nisi vulputate nibh. Fusce varius, ex in rutrum cursus, magna nisl tristique libero, vitae rhoncus ex sapien at odio. Aenean ullamcorper maximus risus, eget ultrices eros auctor eget. Sed mollis blandit tempus. In nec nulla non orci ornare porta in quis velit. Aliquam finibus sodales libero sit amet vulputate. Donec mauris ex, finibus quis sapien ac, laoreet viverra lorem. Curabitur et iaculis dui. Maecenas at volutpat quam. Nulla at venenatis risus. Nunc tempor, erat vitae suscipit pellentesque, risus massa viverra nibh, id lobortis urna turpis id ligula. Curabitur sodales lectus et neque porta maximus. Phasellus tristique dolor quis libero rhoncus, eu sagittis tellus tincidunt.Nam lectus augue, convallis interdum congue nec, condimentum vel ante. Proin malesuada sapien ex, non pulvinar lorem commodo vitae. Donec facilisis mattis odio, sed ultricies lectus dictum ut. In orci lorem, posuere et sodales sed, maximus sit amet justo. Mauris nec mollis orci. Quisque ac vestibulum diam. Sed vel pretium leo, ut eleifend magna. Class aptent taciti sociosqu ad odio \ No newline at end of file diff --git a/exercises/practice/bob/.articles/performance/code/benches/10000_lorem_ipsum_non_ascii.txt b/exercises/practice/bob/.articles/performance/code/benches/10000_lorem_ipsum_non_ascii.txt new file mode 100644 index 000000000..32ed927ad --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/benches/10000_lorem_ipsum_non_ascii.txt @@ -0,0 +1 @@ +O Lorem Ipsum é um tipo de texto de espaço reservado normalmente utilizado nas indústrias de design e publicação para preencher um espaço numa página e dar uma ideia de como será o conteúdo final. Lorem Ipsum em português é derivado de um texto latino do filósofo romano Cícero e tem sido utilizado desde a década de 1960. O texto não faz sentido e não transmite qualquer significado específico, permitindo que os designers se concentrem no layout e nos elementos visuais sem a distração do conteúdo significativo.O texto de espaço reservado é crucial para os designers visualizarem layouts sem distrações do conteúdo real. Permite o foco na estética e na estrutura, garantindo uma apresentação equilibrada. Um layout limpo aumenta a criatividade e facilita a experimentação com tipografia, cores e espaçamento. Esta prática agiliza o processo de design e ajuda as partes interessadas a visualizar o potencial do projeto.Em projetos criativos, o layout é vital para mensagens eficazes. O Lorem Ipsum permite aos designers experimentar vários elementos, permitindo-lhes focar-se na composição sem distrações de conteúdos específicos. Este espaço reservado ao texto ajuda a visualizar a interação entre o texto e as imagens, garantindo um produto final esteticamente agradável e funcional. Também fornece aos clientes uma representação tangível da direção do design, alinhando as expectativas e incentivando o feedback colaborativo.A tipografia é fundamental para um design eficaz, influenciando significativamente a forma como o conteúdo é percecionado. A utilização do Lorem Ipsum em diferentes comprimentos e estilos permite aos designers ver como várias fontes e tamanhos interagem, criando apresentações visualmente coesas. Por exemplo, a combinação de um cabeçalho em negrito com um tipo de letra suave estabelece uma hierarquia que orienta o olhar do visualizador. Esta experimentação é essencial para o desenvolvimento de designs que melhorem a estética e a legibilidade, permitindo aos designers refinar as suas escolhas tipográficas para transmitir o tom e a mensagem pretendidos do conteúdo.Utilizar o Lorem Ipsum em textos em português permite aos designers organizar os elementos de uma forma que guie naturalmente o olhar do espectador pela página. Simplifica o equilíbrio de imagens e espaços em branco sem distrações do conteúdo real, promovendo uma experiência de utilizador limpa e envolvente. Esta abordagem garante que as informações importantes são destacadas, mantendo ao mesmo tempo o apelo visual. Além disso, permite aos designers experimentar vários layouts e estilos sem as restrições do texto real, levando a soluções mais inovadoras que cativam o público.Lorem Ipsum em português é crucial em web design por criar layouts responsivos que se adaptam a diferentes tamanhos de ecrã. Ajuda os designers a simular o fluxo e o ajuste do conteúdo, garantindo uma experiência de utilizador perfeita. Isto é essencial no panorama digital atual, onde os utilizadores acedem a conteúdos em vários dispositivos. O teste de designs com texto fictício permite a identificação precoce de possíveis problemas, permitindo ajustes oportunos que melhoram a usabilidade e a acessibilidade, resultando num produto final mais sofisticado. O Lorem Ipsum é um tipo de texto de espaço reservado normalmente utilizado nas indústrias de design e publicação para preencher um espaço numa página e dar uma ideia de como será o conteúdo final. Lorem Ipsum em português é derivado de um texto latino do filósofo romano Cícero e tem sido utilizado desde a década de 1960. O texto não faz sentido e não transmite qualquer significado específico, permitindo que os designers se concentrem no layout e nos elementos visuais sem a distração do conteúdo significativo.O texto de espaço reservado é crucial para os designers visualizarem layouts sem distrações do conteúdo real. Permite o foco na estética e na estrutura, garantindo uma apresentação equilibrada. Um layout limpo aumenta a criatividade e facilita a experimentação com tipografia, cores e espaçamento. Esta prática agiliza o processo de design e ajuda as partes interessadas a visualizar o potencial do projeto.Em projetos criativos, o layout é vital para mensagens eficazes. O Lorem Ipsum permite aos designers experimentar vários elementos, permitindo-lhes focar-se na composição sem distrações de conteúdos específicos. Este espaço reservado ao texto ajuda a visualizar a interação entre o texto e as imagens, garantindo um produto final esteticamente agradável e funcional. Também fornece aos clientes uma representação tangível da direção do design, alinhando as expectativas e incentivando o feedback colaborativo.A tipografia é fundamental para um design eficaz, influenciando significativamente a forma como o conteúdo é percecionado. A utilização do Lorem Ipsum em diferentes comprimentos e estilos permite aos designers ver como várias fontes e tamanhos interagem, criando apresentações visualmente coesas. Por exemplo, a combinação de um cabeçalho em negrito com um tipo de letra suave estabelece uma hierarquia que orienta o olhar do visualizador. Esta experimentação é essencial para o desenvolvimento de designs que melhorem a estética e a legibilidade, permitindo aos designers refinar as suas escolhas tipográficas para transmitir o tom e a mensagem pretendidos do conteúdo.Utilizar o Lorem Ipsum em textos em português permite aos designers organizar os elementos de uma forma que guie naturalmente o olhar do espectador pela página. Simplifica o equilíbrio de imagens e espaços em branco sem distrações do conteúdo real, promovendo uma experiência de utilizador limpa e envolvente. Esta abordagem garante que as informações importantes são destacadas, mantendo ao mesmo tempo o apelo visual. Além disso, permite aos designers experimentar vários layouts e estilos sem as restrições do texto real, levando a soluções mais inovadoras que cativam o público.Lorem Ipsum em português é crucial em web design por criar layouts responsivos que se adaptam a diferentes tamanhos de ecrã. Ajuda os designers a simular o fluxo e o ajuste do conteúdo, garantindo uma experiência de utilizador perfeita. Isto é essencial no panorama digital atual, onde os utilizadores acedem a conteúdos em vários dispositivos. O teste de designs com texto fictício permite a identificação precoce de possíveis problemas, permitindo ajustes oportunos que melhoram a usabilidade e a acessibilidade, resultando num produto final mais sofisticado. O Lorem Ipsum é um tipo de texto de espaço reservado normalmente utilizado nas indústrias de design e publicação para preencher um espaço numa página e dar uma ideia de como será o conteúdo final. Lorem Ipsum em português é derivado de um texto latino do filósofo romano Cícero e tem sido utilizado desde a década de 1960. O texto não faz sentido e não transmite qualquer significado específico, permitindo que os designers se concentrem no layout e nos elementos visuais sem a distração do conteúdo significativo.O texto de espaço reservado é crucial para os designers visualizarem layouts sem distrações do conteúdo real. Permite o foco na estética e na estrutura, garantindo uma apresentação equilibrada. Um layout limpo aumenta a criatividade e facilita a experimentação com tipografia, cores e espaçamento. Esta prática agiliza o processo de design e ajuda as partes interessadas a visualizar o potencial do projeto.Em projetos criativos, o layout é vital para mensagens eficazes. O Lorem Ipsum permite aos designers experimentar vários elementos, permitindo-lhes focar-se na composição sem distrações de conteúdos específicos. Este espaço reservado ao texto ajuda a visualizar a interação entre o texto e as imagens, garantindo um produto final esteticamente agradável e funcional. Também fornece aos clientes uma representação tangível da direção do design, alinhando as expectativas e incentivando o feedback colaborativo.A tipografia é fundamental para um design eficaz, influenciando significativamente a forma como o conteúdo é percecionado. A utilização do Lorem Ipsum em diferentes comprimentos e estilos permite aos designers ver como várias fontes e tamanhos interagem, criando apresentações visualmente coesas. Por exemplo, a combinação de um cabeçalho em negrito com um tipo de letra suave estabelece uma hierarquia que orienta o olhar do visualizador. Esta experimentação é essencial para o desenvolvimento de designs que melhorem a estética e a legibilidade, permitindo aos designers refinar as suas escolhas tipográficas para transmitir o tom e a mensagem pretendidos do conteúdo.Utilizar o Lorem Ipsum em textos em português permite aos designers organizar os elementos de uma forma que guie naturalmente o olhar do espectador pela página. Simplifica o equilíbrio de imagens e espaços em branco sem distrações do conteúdo real, promovendo uma experiência de utilizador limpa e envolvente. Esta abordagem garante que as informações importantes são destacadas, mantendo ao mesmo tempo o apelo visual. Além disso, permite aos designers experimentar vários layouts e estilos sem as restrições do texto real, levando a soluções mais inovadoras que cativam o público.Lorem Ipsum em português é crucial em web design por criar layouts responsivos que se adaptam a diferentes tamanhos de ecrã. Ajuda os designers a simular o fluxo e o ajuste do conteúdo, garantindo uma experiência de utilizador perfeita. Isto é essencial no panorama digital atual, onde os utilizadores acedem a conteúdos em vários dispositivos. O teste de designs com texto fictício permite a identificação precoce de possíveis problemas, permitindo ajustes oportunos que melhoram a usabilidade e a acessibilidade, resultando num produto final mais sofisticado.O Lorem Ipsum é um tipo de texto de espaço reservado normalmente utilizado nas indústrias de design e publicação para preencher um espaço numa página e dar uma ideia de como será o conteúdo final. Lorem Ipsum em português é derivado de um texto latino do filósofo roma \ No newline at end of file diff --git a/exercises/practice/bob/.articles/performance/code/benches/1000_lorem_ipsum.txt b/exercises/practice/bob/.articles/performance/code/benches/1000_lorem_ipsum.txt new file mode 100644 index 000000000..1495f1a88 --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/benches/1000_lorem_ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ultricies, eros at dictum luctus, metus lectus sollicitudin diam, porttitor feugiat neque metus ut velit. Sed congue nunc quam, ut congue sapien vestibulum sit amet. Ut dignissim purus eros, at gravida mauris interdum vitae. Vivamus molestie rutrum nisi, sed blandit dui pharetra eu. Mauris enim est, commodo in gravida a, suscipit tempor libero. Nulla vel leo non leo tincidunt maximus ac fermentum augue. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse vitae pellentesque libero. Donec eu massa quis mi commodo egestas. Integer tincidunt est non luctus blandit. Praesent rutrum fringilla ligula, in ornare metus mollis at. In mollis metus arcu, sit amet egestas purus pretium vel. Donec a erat a elit gravida dignissim. Nullam rhoncus molestie sapien nec faucibus. Fusce nec posuere felis, nec hendrerit nunc. Vivamus ipsum orci, pharetra a diam ut, sagittis elementum velit orci \ No newline at end of file diff --git a/exercises/practice/bob/.articles/performance/code/benches/1000_lorem_ipsum_non_ascii.txt b/exercises/practice/bob/.articles/performance/code/benches/1000_lorem_ipsum_non_ascii.txt new file mode 100644 index 000000000..a26ef4ba3 --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/benches/1000_lorem_ipsum_non_ascii.txt @@ -0,0 +1 @@ +O Lorem Ipsum é um tipo de texto de espaço reservado normalmente utilizado nas indústrias de design e publicação para preencher um espaço numa página e dar uma ideia de como será o conteúdo final. Lorem Ipsum em português é derivado de um texto latino do filósofo romano Cícero e tem sido utilizado desde a década de 1960. O texto não faz sentido e não transmite qualquer significado específico, permitindo que os designers se concentrem no layout e nos elementos visuais sem a distração do conteúdo significativo.O texto de espaço reservado é crucial para os designers visualizarem layouts sem distrações do conteúdo real. Permite o foco na estética e na estrutura, garantindo uma apresentação equilibrada. Um layout limpo aumenta a criatividade e facilita a experimentação com tipografia, cores e espaçamento. Esta prática agiliza o processo de design e ajuda as partes interessadas a visualizar o potencial do projeto.Em projetos criativos, o layout é vital para mensagens eficazes. O Lorem Ipsum \ No newline at end of file diff --git a/exercises/practice/bob/.articles/performance/code/benches/bob_benchmark.rs b/exercises/practice/bob/.articles/performance/code/benches/bob_benchmark.rs new file mode 100644 index 000000000..7a5e593da --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/benches/bob_benchmark.rs @@ -0,0 +1,276 @@ +use bob_reply::*; +use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; + +const BASIC_LOREM_IPSUM_100: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In arcu justo, facilisis vel leo et sapien"; +const BASIC_LOREM_IPSUM_1000: &str = include_str!("./1000_lorem_ipsum.txt"); +const BASIC_LOREM_IPSUM_10000: &str = include_str!("./10000_lorem_ipsum.txt"); + +const BASIC_LOREM_IPSUM_NON_ASCII_100: &str = "O Lorem Ipsum é um tipo de texto de espaço reservado normalmente utilizado nas indústrias de design e"; +const BASIC_LOREM_IPSUM_NON_ASCII_1000: &str = include_str!("./1000_lorem_ipsum_non_ascii.txt"); +const BASIC_LOREM_IPSUM_NON_ASCII_10000: &str = include_str!("./10000_lorem_ipsum_non_ascii.txt"); + +pub fn reply_for_normal_question(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Sure.\" (normal question)"); + let inputs = vec![ + (0, String::from("?")), + (1, String::from("a?")), + (10, String::from("Hello there?")), // ~10 + (100, format!("{BASIC_LOREM_IPSUM_100}?")), + (1000, format!("{BASIC_LOREM_IPSUM_1000}?")), + (10000, format!("{BASIC_LOREM_IPSUM_10000}?")), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_normal_question_non_ascii(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Sure.\" (normal question + non-ascii)"); + let inputs = vec![ + (0, String::from("?")), + (1, String::from("a?")), + (10, String::from("Hello there?")), // ~10 + (100, format!("{BASIC_LOREM_IPSUM_NON_ASCII_100}?")), + (1000, format!("{BASIC_LOREM_IPSUM_NON_ASCII_1000}?")), + (10000, format!("{BASIC_LOREM_IPSUM_NON_ASCII_10000}?")), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_yell(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Whoa, chill out!\" (yell)"); + let inputs = vec![ + (1, String::from("A")), + (10, String::from("HELLO THERE")), // ~10 + (100, format!("{}", BASIC_LOREM_IPSUM_100.to_uppercase())), + (1000, format!("{}", BASIC_LOREM_IPSUM_1000.to_uppercase())), + (10000, format!("{}", BASIC_LOREM_IPSUM_10000.to_uppercase())), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_yell_non_ascii(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Whoa, chill out!\" (yell + non-ascii)"); + let inputs = vec![ + (1, String::from("A")), + (10, String::from("HELLO THERE")), // ~10 + ( + 100, + format!("{}", BASIC_LOREM_IPSUM_NON_ASCII_100.to_uppercase()), + ), + ( + 1000, + format!("{}", BASIC_LOREM_IPSUM_NON_ASCII_1000.to_uppercase()), + ), + ( + 10000, + format!("{}", BASIC_LOREM_IPSUM_NON_ASCII_10000.to_uppercase()), + ), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_yell_question(c: &mut Criterion) { + let mut group = + c.benchmark_group("Reply: \"Calm down, I know what I'm doing!\" (yell question)"); + let inputs = vec![ + (1, String::from("A?")), + (10, String::from("HELLO THERE?")), // ~10 + (100, format!("{}?", BASIC_LOREM_IPSUM_100.to_uppercase())), + (1000, format!("{}?", BASIC_LOREM_IPSUM_1000.to_uppercase())), + ( + 10000, + format!("{}?", BASIC_LOREM_IPSUM_10000.to_uppercase()), + ), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_yell_question_non_ascii(c: &mut Criterion) { + let mut group = c.benchmark_group( + "Reply: \"Calm down, I know what I'm doing!\" (yell question + non-ascii)", + ); + let inputs = vec![ + (1, String::from("A?")), + (10, String::from("HELLO THERE?")), // ~10 + ( + 100, + format!("{}?", BASIC_LOREM_IPSUM_NON_ASCII_100.to_uppercase()), + ), + ( + 1000, + format!("{}?", BASIC_LOREM_IPSUM_NON_ASCII_1000.to_uppercase()), + ), + ( + 10000, + format!("{}?", BASIC_LOREM_IPSUM_NON_ASCII_10000.to_uppercase()), + ), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_silence(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Fine.Be that way!\" (empty array or whitespace)"); + let inputs = vec![ + "".to_string(), + " ".to_string(), + " ".repeat(10), + " ".repeat(100), + " ".repeat(1000), + " ".repeat(10000), + ]; + for i in inputs { + group.bench_with_input(BenchmarkId::new("Array", i.len()), &i, |b, i| { + b.iter(|| reply_array(i)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i.len()), &i, |b, i| { + b.iter(|| reply_if_chain(i)) + }); + group.bench_with_input(BenchmarkId::new("Match", i.len()), &i, |b, i| { + b.iter(|| reply_match(i)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i.len()), &i, |b, i| { + b.iter(|| reply_state_machine(i)) + }); + } +} + +pub fn reply_for_whatever(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Whatever.\" (any other)"); + let inputs = vec![ + (1, String::from("a")), + (10, String::from("Hello there")), // ~10 + (100, format!("{BASIC_LOREM_IPSUM_100}")), + (1000, format!("{BASIC_LOREM_IPSUM_1000}")), + (10000, format!("{BASIC_LOREM_IPSUM_10000}")), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +pub fn reply_for_whatever_non_ascii(c: &mut Criterion) { + let mut group = c.benchmark_group("Reply: \"Whatever.\" (any other + non-ascii)"); + let inputs = vec![ + (1, String::from("a")), + (10, String::from("Hello there")), // ~10 + (100, format!("{BASIC_LOREM_IPSUM_NON_ASCII_100}")), + (1000, format!("{BASIC_LOREM_IPSUM_NON_ASCII_1000}")), + (10000, format!("{BASIC_LOREM_IPSUM_NON_ASCII_10000}")), + ]; + for (i, input) in inputs { + group.bench_with_input(BenchmarkId::new("Array", i), &input, |b, input| { + b.iter(|| reply_array(input)) + }); + group.bench_with_input(BenchmarkId::new("If Chain", i), &input, |b, input| { + b.iter(|| reply_if_chain(input)) + }); + group.bench_with_input(BenchmarkId::new("Match", i), &input, |b, input| { + b.iter(|| reply_match(input)) + }); + group.bench_with_input(BenchmarkId::new("State Machine", i), &input, |b, input| { + b.iter(|| reply_state_machine(input)) + }); + } +} + +criterion_group!( + benches, + reply_for_normal_question, + reply_for_normal_question_non_ascii, + reply_for_yell, + reply_for_yell_non_ascii, + reply_for_yell_question, + reply_for_yell_question_non_ascii, + reply_for_silence, + reply_for_whatever, + reply_for_whatever_non_ascii +); +criterion_main!(benches); diff --git a/exercises/practice/bob/.articles/performance/code/benches/test.rs b/exercises/practice/bob/.articles/performance/code/benches/test.rs new file mode 100644 index 000000000..d113c9b4a --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/benches/test.rs @@ -0,0 +1,94 @@ +use bob_reply::{reply_array, reply_if_chain, reply_match, reply_state_machine}; + +const BASIC_LOREM_IPSUM_100: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In arcu justo, facilisis vel leo et sapien"; +const BASIC_LOREM_IPSUM_1000: &str = include_str!("./1000_lorem_ipsum.txt"); +const BASIC_LOREM_IPSUM_10000: &str = include_str!("./10000_lorem_ipsum.txt"); + +const BASIC_LOREM_IPSUM_NON_ASCII_100: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing èlit. În arcu justo, facilisis vel leo et sapien"; +const BASIC_LOREM_IPSUM_NON_ASCII_1000: &str = include_str!("./1000_lorem_ipsum_non_ascii.txt"); +const BASIC_LOREM_IPSUM_NON_ASCII_10000: &str = include_str!("./10000_lorem_ipsum_non_ascii.txt"); + +#[test] +fn test_normal_question() { + let inputs = vec![ + String::from("?"), + String::from("a?"), + String::from("Hello there?"), // ~10 + format!("{BASIC_LOREM_IPSUM_100}?"), + format!("{BASIC_LOREM_IPSUM_1000}?"), + format!("{BASIC_LOREM_IPSUM_10000}?"), + format!("{BASIC_LOREM_IPSUM_NON_ASCII_100}?"), + format!("{BASIC_LOREM_IPSUM_NON_ASCII_1000}?"), + format!("{BASIC_LOREM_IPSUM_NON_ASCII_10000}?"), + ]; + let expected = "Sure."; + for input in inputs { + assert_eq!(reply_array(input.as_str()), expected); + assert_eq!(reply_if_chain(input.as_str()), expected); + assert_eq!(reply_match(input.as_str()), expected); + assert_eq!(reply_state_machine(input.as_str()), expected); + } +} + +#[test] +fn test_yell() { + let inputs = vec![ + String::from("A"), + String::from("HELLO THERE"), // ~10 + format!("{}", BASIC_LOREM_IPSUM_100.to_uppercase()), + format!("{}", BASIC_LOREM_IPSUM_1000.to_uppercase()), + format!("{}", BASIC_LOREM_IPSUM_10000.to_uppercase()), + format!("{}", BASIC_LOREM_IPSUM_NON_ASCII_100.to_uppercase()), + format!("{}", BASIC_LOREM_IPSUM_NON_ASCII_1000.to_uppercase()), + format!("{}", BASIC_LOREM_IPSUM_NON_ASCII_10000.to_uppercase()), + ]; + let expected = "Whoa, chill out!"; + for input in inputs { + assert_eq!(reply_array(input.as_str()), expected); + assert_eq!(reply_if_chain(input.as_str()), expected); + assert_eq!(reply_match(input.as_str()), expected); + assert_eq!(reply_state_machine(input.as_str()), expected); + } +} + +#[test] +fn test_yell_question() { + let inputs = vec![ + String::from("A?"), + String::from("HELLO THERE?"), // ~10 + format!("{}?", BASIC_LOREM_IPSUM_100.to_uppercase()), + format!("{}?", BASIC_LOREM_IPSUM_1000.to_uppercase()), + format!("{}?", BASIC_LOREM_IPSUM_10000.to_uppercase()), + format!("{}?", BASIC_LOREM_IPSUM_NON_ASCII_100.to_uppercase()), + format!("{}?", BASIC_LOREM_IPSUM_NON_ASCII_1000.to_uppercase()), + format!("{}?", BASIC_LOREM_IPSUM_NON_ASCII_10000.to_uppercase()), + ]; + let expected = "Calm down, I know what I'm doing!"; + for input in inputs { + assert_eq!(reply_array(input.as_str()), expected); + assert_eq!(reply_if_chain(input.as_str()), expected); + assert_eq!(reply_match(input.as_str()), expected); + assert_eq!(reply_state_machine(input.as_str()), expected); + } +} + +#[test] +fn test_whatever() { + let inputs = vec![ + String::from("a"), + String::from("Hello there"), // ~10 + format!("{BASIC_LOREM_IPSUM_100}"), + format!("{BASIC_LOREM_IPSUM_1000}"), + format!("{BASIC_LOREM_IPSUM_10000}"), + format!("{BASIC_LOREM_IPSUM_NON_ASCII_100}"), + format!("{BASIC_LOREM_IPSUM_NON_ASCII_1000}"), + format!("{BASIC_LOREM_IPSUM_NON_ASCII_10000}"), + ]; + let expected = "Whatever."; + for input in inputs { + assert_eq!(reply_array(input.as_str()), expected); + assert_eq!(reply_if_chain(input.as_str()), expected); + assert_eq!(reply_match(input.as_str()), expected); + assert_eq!(reply_state_machine(input.as_str()), expected); + } +} diff --git a/exercises/practice/bob/.articles/performance/code/main.rs b/exercises/practice/bob/.articles/performance/code/main.rs deleted file mode 100644 index ffff8656c..000000000 --- a/exercises/practice/bob/.articles/performance/code/main.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![feature(test)] -extern crate test; -use test::Bencher; - -fn main() { - println!("Hello, world!"); -} - -pub fn reply_match(msg: &str) -> &str { - let message = msg.trim_end(); - if message.is_empty() { - return "Fine. Be that way!"; - } - - let is_questioning = message.ends_with('?'); - let is_yelling = - message.chars().any(|ch| ch.is_alphabetic()) && message == message.to_uppercase(); - - match (is_yelling, is_questioning) { - (true, true) => "Calm down, I know what I'm doing!", - (true, _) => "Whoa, chill out!", - (_, true) => "Sure.", - _ => "Whatever.", - } -} - -pub fn reply_if_chain(msg: &str) -> &str { - let message = msg.trim_end(); - if message.is_empty() { - return "Fine. Be that way!"; - } - - let is_questioning = message.ends_with('?'); - let is_yelling = - message.chars().any(|ch| ch.is_alphabetic()) && message == message.to_uppercase(); - - if is_yelling { - return if is_questioning { - "Calm down, I know what I'm doing!" - } else { - "Whoa, chill out!" - }; - } - if is_questioning { - return "Sure."; - } - "Whatever." -} - -const ANSWERS: &'static [&'static str] = &[ - "Whatever.", - "Sure.", - "Whoa, chill out!", - "Calm down, I know what I'm doing!", -]; - -pub fn reply_array(msg: &str) -> &str { - let message = msg.trim_end(); - if message.is_empty() { - return "Fine. Be that way!"; - } - - let is_questioning = if message.ends_with('?') { 1 } else { 0 }; - let is_yelling = - if message.chars().any(|ch| ch.is_alphabetic()) && message == message.to_uppercase() { - 2 - } else { - 0 - }; - - ANSWERS[is_questioning + is_yelling] -} - -#[bench] -/// multiple line question for match -fn multiple_line_question_match(b: &mut Bencher) { - b.iter(|| reply_match("\rDoes this cryogenic chamber make me look fat?\rNo.")); -} - -#[bench] -/// multiple line question for if statements -fn multiple_line_question_if(b: &mut Bencher) { - b.iter(|| reply_if_chain("\rDoes this cryogenic chamber make me look fat?\rNo.")); -} - -#[bench] -/// multiple line question for answer array -fn multiple_line_question_array(b: &mut Bencher) { - b.iter(|| reply_array("\rDoes this cryogenic chamber make me look fat?\rNo.")); -} diff --git a/exercises/practice/bob/.articles/performance/code/src/lib.rs b/exercises/practice/bob/.articles/performance/code/src/lib.rs new file mode 100644 index 000000000..8ad0449d6 --- /dev/null +++ b/exercises/practice/bob/.articles/performance/code/src/lib.rs @@ -0,0 +1,335 @@ +// Reply using match +pub fn reply_match(msg: &str) -> &str { + let message = msg.trim_end(); + if message.is_empty() { + return "Fine. Be that way!"; + } + + let is_questioning = message.ends_with('?'); + let is_yelling = + message.chars().any(|ch| ch.is_alphabetic()) && message == message.to_uppercase(); + + match (is_yelling, is_questioning) { + (true, true) => "Calm down, I know what I'm doing!", + (true, _) => "Whoa, chill out!", + (_, true) => "Sure.", + _ => "Whatever.", + } +} + +// Reply using if chain +pub fn reply_if_chain(msg: &str) -> &str { + let message = msg.trim_end(); + if message.is_empty() { + return "Fine. Be that way!"; + } + + let is_questioning = message.ends_with('?'); + let is_yelling = + message.chars().any(|ch| ch.is_alphabetic()) && message == message.to_uppercase(); + + if is_yelling { + return if is_questioning { + "Calm down, I know what I'm doing!" + } else { + "Whoa, chill out!" + }; + } + if is_questioning { + return "Sure."; + } + "Whatever." +} + +// Reply using array +const ANSWERS: &[&str] = &[ + "Whatever.", + "Sure.", + "Whoa, chill out!", + "Calm down, I know what I'm doing!", +]; + +pub fn reply_array(msg: &str) -> &str { + let message = msg.trim_end(); + if message.is_empty() { + return "Fine. Be that way!"; + } + + let is_questioning = if message.ends_with('?') { 1 } else { 0 }; + let is_yelling = + if message.chars().any(|ch| ch.is_alphabetic()) && message == message.to_uppercase() { + 2 + } else { + 0 + }; + + ANSWERS[is_questioning + is_yelling] +} + +// Reply using state machine +#[derive(Hash, Eq, PartialEq, Debug)] +enum State { + Initial, + HasQuestionMark, + NoQuestionMarkUpperCase, + NoQuestionMarkUndefined, + QuestionMarkUpperCase, + QuestionMarkUndefined, +} +enum NextStateResult { + NextState(State), + FinalResult(&'static str), +} +impl State { + fn next_state(self, c: char) -> NextStateResult { + match self { + State::Initial => { + if c == '?' { + return NextStateResult::NextState(State::HasQuestionMark); + } + + if c.is_lowercase() { + return NextStateResult::FinalResult(WHATEVER); + } + if c.is_uppercase() { + return NextStateResult::NextState(State::NoQuestionMarkUpperCase); + } + NextStateResult::NextState(State::NoQuestionMarkUndefined) + } + State::HasQuestionMark => { + if c.is_uppercase() { + return NextStateResult::NextState(State::QuestionMarkUpperCase); + } + if c.is_lowercase() { + return NextStateResult::FinalResult(SURE); + } + NextStateResult::NextState(State::QuestionMarkUndefined) + } + // optimize + State::NoQuestionMarkUpperCase => { + if c.is_lowercase() { + return NextStateResult::FinalResult(WHATEVER); + } + NextStateResult::NextState(self) + } + State::NoQuestionMarkUndefined => { + if c.is_lowercase() { + return NextStateResult::FinalResult(WHATEVER); + } + if c.is_uppercase() { + return NextStateResult::NextState(State::NoQuestionMarkUpperCase); + } + NextStateResult::NextState(self) + } + State::QuestionMarkUpperCase => { + if c.is_lowercase() { + return NextStateResult::FinalResult(SURE); + } + NextStateResult::NextState(self) + } + State::QuestionMarkUndefined => { + if c.is_lowercase() { + return NextStateResult::FinalResult(SURE); + } + if c.is_uppercase() { + return NextStateResult::NextState(State::QuestionMarkUpperCase); + } + NextStateResult::NextState(self) + } + } + } +} + +const FINE_BE_THAT_WAY: &str = "Fine. Be that way!"; +const WHATEVER: &str = "Whatever."; +const SURE: &str = "Sure."; +const CHILL_OUT: &str = "Whoa, chill out!"; +const CALM_DOWN: &str = "Calm down, I know what I'm doing!"; + +pub fn reply_state_machine(message: &str) -> &str { + let message = message.trim_end(); + if message.is_empty() { + return FINE_BE_THAT_WAY; + } + let mut state = State::Initial; + for c in message.chars().rev() { + match state.next_state(c) { + NextStateResult::NextState(s) => state = s, + NextStateResult::FinalResult(r) => return r, + } + } + match state { + State::HasQuestionMark | State::QuestionMarkUndefined => SURE, + State::NoQuestionMarkUpperCase => CHILL_OUT, + State::NoQuestionMarkUndefined => WHATEVER, + State::QuestionMarkUpperCase => CALM_DOWN, + _ => panic!("Unexpected final state"), + } +} + +macro_rules! test_reply { + ( $( ($function_name:ident, $module_name:ident)),* ) => { + + $( + mod $module_name{ + #[allow(unused_imports)] + use super::*; + + #[test] + fn stating_something() { + assert_eq!($function_name("Tom-ay-to, tom-aaaah-to."), "Whatever."); + } + + #[test] + fn shouting() { + assert_eq!($function_name("WATCH OUT!"), "Whoa, chill out!"); + } + + #[test] + fn shouting_gibberish() { + assert_eq!($function_name("FCECDFCAAB"), "Whoa, chill out!"); + } + + #[test] + fn asking_a_question() { + assert_eq!( + $function_name("Does this cryogenic chamber make me look fat?"), + "Sure." + ); + } + + #[test] + fn asking_a_numeric_question() { + assert_eq!($function_name("You are, what, like 15?"), "Sure."); + } + + #[test] + fn asking_gibberish() { + assert_eq!($function_name("fffbbcbeab?"), "Sure."); + } + + #[test] + fn talking_forcefully() { + assert_eq!($function_name("Hi there!"), "Whatever."); + } + + #[test] + fn using_acronyms_in_regular_speech() { + assert_eq!( + $function_name("It's OK if you don't want to go work for NASA."), + "Whatever." + ); + } + + #[test] + fn forceful_question() { + assert_eq!( + $function_name("WHAT'S GOING ON?"), + "Calm down, I know what I'm doing!" + ); + } + + #[test] + fn shouting_numbers() { + assert_eq!($function_name("1, 2, 3 GO!"), "Whoa, chill out!"); + } + + #[test] + fn no_letters() { + assert_eq!($function_name("1, 2, 3"), "Whatever."); + } + + #[test] + fn question_with_no_letters() { + assert_eq!($function_name("4?"), "Sure."); + } + + #[test] + fn shouting_with_special_characters() { + assert_eq!( + $function_name("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"), + "Whoa, chill out!" + ); + } + + #[test] + fn shouting_with_no_exclamation_mark() { + assert_eq!($function_name("I HATE THE DENTIST"), "Whoa, chill out!"); + } + + #[test] + fn statement_containing_question_mark() { + assert_eq!($function_name("Ending with ? means a question."), "Whatever."); + } + + #[test] + fn non_letters_with_question() { + assert_eq!($function_name(":) ?"), "Sure."); + } + + #[test] + fn prattling_on() { + assert_eq!($function_name("Wait! Hang on. Are you going to be OK?"), "Sure."); + } + + #[test] + fn silence() { + assert_eq!($function_name(""), "Fine. Be that way!"); + } + + #[test] + fn prolonged_silence() { + assert_eq!($function_name(" "), "Fine. Be that way!"); + } + + #[test] + fn alternate_silence() { + assert_eq!($function_name("\t\t\t\t\t\t\t\t\t\t"), "Fine. Be that way!"); + } + + #[test] + fn starting_with_whitespace() { + assert_eq!($function_name(" hmmmmmmm..."), "Whatever."); + } + + #[test] + fn ending_with_whitespace() { + assert_eq!($function_name("Okay if like my spacebar quite a bit? "), "Sure."); + } + + #[test] + fn other_whitespace() { + assert_eq!($function_name("\n\r \t"), "Fine. Be that way!"); + } + + #[test] + fn non_question_ending_with_whitespace() { + assert_eq!( + $function_name("This is a statement ending with whitespace "), + "Whatever." + ); + } + + #[test] + fn multiple_line_question() { + assert_eq!( + $function_name("\nDoes this cryogenic chamber make\n me look fat?"), + "Sure." + ); + } + } + )* + }; +} + +mod tests { + #[allow(unused_imports)] + use super::*; + + test_reply!( + (reply_match, reply_match_test), + (reply_if_chain, reply_if_chain_test), + (reply_array, reply_array_test), + (reply_state_machine, reply_state_machine_test) + ); +} diff --git a/exercises/practice/bob/.articles/performance/content.md b/exercises/practice/bob/.articles/performance/content.md index d24be3298..7c209f4f4 100644 --- a/exercises/practice/bob/.articles/performance/content.md +++ b/exercises/practice/bob/.articles/performance/content.md @@ -1,28 +1,69 @@ # Performance -In this approach, we'll find out how to most efficiently determine the response for Bob in Rust. +By using [criterion crate][criterion-crate], we'll find out how to most efficiently determine the response for Bob in Rust. The [approaches page][approaches] lists two idiomatic approaches to this exercise: 1. [Using `if` statements][approach-if]. 2. [Using `match` on a `tuple`][approach-match]. -For our performance investigation, we'll also include a third approach that [uses an answer array][approach-answer-array]. +For our performance investigation, we'll also include a third approach that [uses an answer array][approach-answer-array], and a fourth that uses a state machine. + +The code used in the benchmark can be found [here][benchmark-application]. ## Benchmarks -To benchmark the approaches, we wrote a [small benchmark application][benchmark-application]. +The strategy used to build the benchmark was to create groups to test different situations for each of the 4 approaches. Thus, for each group, each of the 4 approaches were independently tested. +The groups were designed to cover all the possible replies from Bob. Also, for each reply (with exception for the `silence` reply), both ASCII and non-ASCII text inputs were used. Given that Bob may have 5 types of replies, we have a total of 9 groups (4 groups with ascii and non-ascii input versions and the `silence` reply). + +Possible replies from Bob: + 1. "Sure" to normal question + 2. "Whoa, chill out!" to yell. + 3. "Calm down, I know what I'm doing!" to yell question. + 4. "Fine. Be that way!" to silence. + 5. "Whatever." to anything else. + +Also, to make it possible for us to see the difference in performance, for each group, 5 different inputs were used, ranging in number of chars as follows: [1, 10, 100, 1000, 10.000]. For inputs with size greater than or equal to 100, an ascii and non-ascii versions of the [lorem ipsum][lorem-ipsum] text were used. + +The groups are prefixed with `reply_for_`: +```rust +//... +criterion_group!( + benches, + reply_for_normal_question, + reply_for_normal_question_non_ascii, + reply_for_yell, + reply_for_yell_non_ascii, + reply_for_yell_question, + reply_for_yell_question_non_ascii, + reply_for_silence, + reply_for_whatever, + reply_for_whatever_non_ascii +); ``` -test multiple_line_question_match ... bench: 96 ns/iter (+/- 17) -test multiple_line_question_if ... bench: 97 ns/iter (+/- 12) -test multiple_line_question_array ... bench: 100 ns/iter (+/- 2) -``` -All three approaches are close in performance, but the `if` statements and `match` approaches may be considered to be more idiomatic. +### Results + +The detailed results will be in the `report` folder generated after running the benchmark. + +Generally speaking, the results were: + - **For YELL and YELL QUESTION**: one of the state machine's worst case because it needs to loop through all the string to find the answer. Thus, it **performed worse than the other approaches for lore ipsum with only ascii chars** but, surprisingly, **performed better for lore ipsum with ascii and non-ascii chars**. The explanation is that the other approaches could not take advantage of this [ascii optimization][ascii-optimization]. + - **For normal question and whatever**: state machine performed better than the other approaches, but that happened because the lorem ipsum has lower case chars distributed along the string, including the end of the string, which makes it almost O(1) for finding the answer. It is possible to build a worst case situation for the state machine in which all the chars are uppercase except the first, making it necessary to loop through all the chars. In that situation, we would have something close to the YELL and YELL QUESTION. + - **For the empty answer**: For that specific situation, all the approaches are optimized. + + +Excluding the state machine approach, the other three approaches are close in performance, but the `if` statements and `match` approaches may be considered to be more idiomatic. + +### Reproducing the results + +To reproduce the results, run the command `cargo bench` from the [benchmark application][benchmark-application] directory. Be aware that it may take a long time. After finishing the execution, the results can be found on `results/criterion/report/index.html`. [approaches]: https://exercism.org/tracks/rust/exercises/bob/approaches +[approach-answer-array]: https://exercism.org/tracks/rust/exercises/bob/approaches/answer-array [approach-if]: https://exercism.org/tracks/rust/exercises/bob/approaches/if-statements [approach-match]: https://exercism.org/tracks/rust/exercises/bob/approaches/match-on-tuple -[approach-answer-array]: https://exercism.org/tracks/rust/exercises/bob/approaches/answer-array -[benchmark-application]: https://github.com/exercism/rust/blob/main/exercises/practice/bob/.articles/performance/code/main.rs +[ascii-optimization]: https://github.com/rust-lang/rust/blob/7d65abfe80f9eee93296d1ce08f845c9bf7039f8/library/alloc/src/str.rs#L471 +[benchmark-application]: https://github.com/exercism/rust/blob/main/exercises/practice/bob/.articles/performance/code/ +[criterion-crate]: https://docs.rs/criterion/latest/criterion/ +[lorem-ipsum]: https://en.wikipedia.org/wiki/Lorem_ipsum