🤔 Para Refletir : "Não force a criatividade, liberte a sua mente e a criatividade virá." - Frank

DESAFIO: Código Maldito

Estado
Tópico fechado. Não é possível fazer postagens nela.
Administração Administração
Jogador maluco, problemático, olho parado.
Postagens
538
Bravecoins
2.489
Área
Programação
Motor de jogo
RPG Maker 2003
mini-banner-codigo-maldito-png.6449

Na Torre do Desespero, na fronteira gelada do Condado Braveheart, vive um Cientista Louco, imerso em seus cálculos e experimentos ele vive preso em devaneios de sua mente criando enigmas infinitos e largando-os no caminho a sua solitária torre, aguardando alguém que possa solucionar seus problemas...



Um grupo de crianças encontrou uma caixa com diversos brinquedos para se divertirem no Halloween. Nessa caixa eles encontraram:​
  • Aranhas de plástico​
  • Sapos de borracha​
  • Dentaduras​
  • Fantasminhas que brilham no escuro​
  • Bruxinhas​
JC, Hellen, Franklin, Daniel e Samuel gostaram da caixa e decidiram distribuir os brinquedos de acordo com seus gostos. Mas como Samuel é um menino que gosta criar brincadeira com qualquer coisa com seus amigos e resolveu propor um pequeno jogo para eles. Mas antes disso, Samuel resolveu colocar seus amigos em uma fila de frente à caixa, na seguinte ordem:​
  • Samuel​
  • Franklin​
  • Hellen​
  • JC​
  • Daniel​
Feito isso, Samuel sempre retirará um brinquedo da caixa e o brinquedo será passado para as crianças de mão em mão, respeitando a ordem da fila até uma delas pegar o brinquedo que ela gosta. Se a criança receber um brinquedo que ela gosta, pegará para ela e guardará em sua mochila. Se o brinquedo é aquele que a criança não gosta, passa para a próxima que está atrás.
Abaixo, temos informações importantes para descobrir qual brinquedo cada criança gosta.​
  1. Hellen gosta de Fantasminhas que brilham no escuro.​
  2. Daniel nunca vai receber Bruxinhas.​
  3. Franklin não gosta de Bruxinhas.​
  4. As outras crianças nunca receberão Sapos de borracha.​
  5. As Dentaduras sempre serão passadas para todas as crianças.​
Desenvolva um código que faz a distribuição dos brinquedos para cada criança. A linguagem ficará à sua escolha, no entanto você deverá escolher 1 (um) paradigma ou 3 (três):​
  • Imperativa Estruturada​
  • Imperativa Orientada a Objetos​
  • Declarativa Funcional​
Se o participante escolher 2 (dois) paradigmas, será considerado somente o primeiro paradigma escolhido seguindo a ordem da lista acima.


É preferível que o participante envie a solução através de um repositório Git (pode ser qualquer plataforma que usa Git: Github, Gitlab, Bitbucket, etc.). Se não tiver como enviar como repositório, pode enviar todo o código aqui como resposta a este tópico, mas precisa especificar a estrutura dos arquivos separadamente e os códigos de cada um deles, se for necessário.
Recomendamos que coloque a solução dentro do spoiler para que os outros participantes acabem não vendo sem querer e/ou ser influenciado pela resposta do outro participante.
Não será considerado como aprovado qualquer outra forma de padronização de envio. Em caso de quaisquer dúvidas, não hesite em usar o espaço deste tópico para poder saná-las o quanto antes.


Use o modelo abaixo se não for enviar via Github.
Estrutura:
Código:
App/
    Person.php
index.php

App/Person.php
Php:
<?php

namespace App;

class Person
{
    public function __construct(
        private string $name,
        private int $age
    )
    {}


    public function __get(string $key)
    {
        if (property_exists($this, $key))
            return $this->$key;
        return null;
    }


    public function __set(string $key, $value)
    {
        if (property_exists($this, $key))
            $this->$key = $value;
    }
}

index.php
Php:
<?php

use App\Person;

/** @var Person */
$person = new Person('Jubileu', 21);
echo 'Nome: ' . $person->name;
echo 'Idade: ' . $person->age;



A resolução do código será testada em um ambiente de testes unitários para validação da solução. Se o problema for resolvido em um dos paradigmas selecionados e passar por todos os testes, o participante receberá 100 Bravecoins.
O participante também pode tentar escolher os 3 paradigmas. Cada código vai um bônus de 50 Bravecoins para cada teste aprovado. Se os 3 códigos passarem nos testes, ainda terão um bônus de 50 Bravecoins por desenvolver a mesma solução em 3 paradigmas diferentes.


Escolheu um paradigma e passou no teste+100 Bravecoins
Escolheu os 3 paradigmas e, pelo menos, um dos testes passou+100 Bravecoins +50/teste aprovado
Escolheu os 3 paradigmas e os todos eles passaram no teste+100 Bravecoins +150 Bravecoins + 50 Bravecoins
 
Última edição:
Minha entrega
Eu fiz o código em duas versões: com recursão e sem recursão (tem pastas separadas para cada sln).
Eu sei q mudar o jeito de fazer não dá pontos extras, mas a versão com recursão é mais divertida de ver funcionando "step-by-step." :D
Se quiserem considerar alguma das duas versões como a"oficial" para avaliação, pode ser a sem recursão, que foi a q eu fiz primeiro.
Espero ter acertado a charada, pelo menos '-'

Edit: já ia esquecendo, eu fiz em C# com POO.
 
A linguagem ficará à sua escolha

200w.gif


(Ocasião errada, sim, mas o GIF era bom demais)



Fiz aqui, em Lean 4: https://github.com/masked-rpgmaker/cursed-code

Eu ia fazer estruturado em alguma coisa tipo ALGOL 60 e orientado a objetos em Smalltalk, mas não tive paciência de achar um compilador/interpretador que funcionasse e não fosse uma dor de cabeça de usar. Então ficou tudo em Lean mesmo rs

Tecnicamente as três soluções são puramente funcionais (porque a linguagem em si é; tudo que parece não ser funcional é syntax sugar em cima de alguma mônada ahueha), mas cada uma segue um dos paradigmas estipulados.

A orientação a objetos é meio rudimentar, mas segue a ideia central dos dados e comportamento centralizados nos objetos, encapsulamento, e troca de mensagens; na prática, se fizesse em Smalltalk, por exemplo, ia ficar praticamente a mesma coisa (a diferença é que Lean não tem muita sintaxe pra isso, eu até podia ter escrito umas macros, mas já sofri demais com isso aqui rs). Também tomei cuidado de não abusar muito da programação funcional, então fora as definições (que tem as mônadas e umas funções de segunda ordem ali) tá tudo na base de estruturas de repetição e dados "mutáveis" (tecnicamente é tudo persistente, mas no código e em efeito parece que é mutável).

A implementação estruturada é estruturada num sentido meio técnico, evitei até usar break. Mas pelo menos acho que não tem muito o que dizer que não tá imperativo e/ou estruturado ali.

O legal de usar Lean é que consegui provar que a função de gostos das crianças tá correta (aqui) usando as informações do enunciado como axiomas, e que o programa funcional gera a saída certa (aqui; só provei pro funcional porque é o mais passível desse tipo de demonstração, os outros ia ser zoadão de provar, com as mônadas espalhadas em todo lugar; ao mesmo tempo, é só comparar a saída com a do funcional hehe).

Só tive que presumir uma informação adicional, que tá meio implícita no enunciado: cada criança termina a brincadeira com exatamente um brinquedo (e todo brinquedo vai parar na mão de alguma criança). Sem essa hipótese não dá pra provar as coisas por exclusão, e aí quebra um pouco as pernas.

De toda forma, maneiro o evento, valeu cenourão \o
 
Rapaziada, fiz um vídeo no meu canal para complementar este tópico do desafio.





@Mayleone e @Brandt , não me esqueci de vocês. Analisarei as soluções com muito carinho e logo darei um retorno ❤️




Só tive que presumir uma informação adicional, que tá meio implícita no enunciado: cada criança termina a brincadeira com exatamente um brinquedo (e todo brinquedo vai parar na mão de alguma criança).
Essa parte eu deixei à liberdade do desenvolvedor. A caixa poderia conter vários brinquedo repetidos (5 aranhas, 3 bruxinhas, 10 dentaduras, etc.) assim como pode ter caixas que pode não ter o brinquedo listado no enunciado. Permitindo ir além: a caixa possuir algum outro brinquedo que não consta na lista que vcs podem criar para este cenário para testar diversos comportamentos do programa.
Por isso deixei essa informação meio solta, pq a ideia é fazer o sistema funcionar sem se importar com o que há dentro da caixa. Portanto, sem problemas. Tanto o que vc fez quanto ao que a May fez estão corretos.
 
Minha entrega
Eu fiz o código em duas versões: com recursão e sem recursão (tem pastas separadas para cada sln).
Eu sei q mudar o jeito de fazer não dá pontos extras, mas a versão com recursão é mais divertida de ver funcionando "step-by-step." :D
Se quiserem considerar alguma das duas versões como a"oficial" para avaliação, pode ser a sem recursão, que foi a q eu fiz primeiro.
Espero ter acertado a charada, pelo menos '-'

Edit: já ia esquecendo, eu fiz em C# com POO.

Acabei de avaliar sua solução. Precisei adaptá-lo para aceitar uma lista de brinquedos recebidos de um arquivo de texto separado por linhas para rodar nos testes. Peguei a solução sem recursão e coloquei seu programa para rodar com 50 caixas com uma variedade de brinquedos diferentes, incluindo uma das caixas sendo vazia.

Bem... vamos falar do código em si. Embora vc tenha escolhido o paradigma Orientado a Objetos, eu enxerguei o código como Estruturado por conta das chamadas estáticas ali tudo na classe principal do programa sem que haja de fato uma comunicação entre as instâncias da criança e do brinquedo.
Mas isso não é um problema, continua valendo do mesmo jeito :^-^:

E como a regra é clara: Programa rodou? Resolveu o problema?
Então PONTO PARA A MAYLEONE! :wink:




Agora um extra se vc tiver interesse, é claro.
Durantes os 50 testes, tivemos uma falha em uma das caixas, que foi a caixa vazia (Caixa #13). O programa caiu em um loop infinito e ele precisou ser abortado.
Você pode refatorar a sua solução para que ela funcione sem se importar com que há dentro da caixa e que a bolsa da criança possa caber mais brinquedos dentro caso receba o mesmo brinquedo mais de uma vez.
Fica um desafio extra se quiser fazê-lo. Vai que o Broba libera mais verba kkkkkkkkk !!

Você pode acessar os relatórios dos testes aqui. E para te auxiliar, vou disponibilizar para vocês a lista das caixas que estou usando para testar os programas de vocês. ;)




OFF:
Achei muito legal a solução com recursão. Ele ficou mais elegante que o código sem recursão (que não deixa de ser elegante por isso).
E sim, vc acertou a charada na mosca *:)
 
Opa, adorei! Haha
Realmente não me liguei na questão da caixa, eu não sei pq, mas quando li o enunciado pensei q a caixa tivesse exatamente 5 brinquedos, um de cada, talvez seja por isso q não me atentei a prever a questão de ter vários brinquedos ou até mesmo nenhum!
Vou fazer um update sim, hein.
 
200w.gif


(Ocasião errada, sim, mas o GIF era bom demais)



Fiz aqui, em Lean 4: https://github.com/masked-rpgmaker/cursed-code

Eu ia fazer estruturado em alguma coisa tipo ALGOL 60 e orientado a objetos em Smalltalk, mas não tive paciência de achar um compilador/interpretador que funcionasse e não fosse uma dor de cabeça de usar. Então ficou tudo em Lean mesmo rs

Tecnicamente as três soluções são puramente funcionais (porque a linguagem em si é; tudo que parece não ser funcional é syntax sugar em cima de alguma mônada ahueha), mas cada uma segue um dos paradigmas estipulados.

A orientação a objetos é meio rudimentar, mas segue a ideia central dos dados e comportamento centralizados nos objetos, encapsulamento, e troca de mensagens; na prática, se fizesse em Smalltalk, por exemplo, ia ficar praticamente a mesma coisa (a diferença é que Lean não tem muita sintaxe pra isso, eu até podia ter escrito umas macros, mas já sofri demais com isso aqui rs). Também tomei cuidado de não abusar muito da programação funcional, então fora as definições (que tem as mônadas e umas funções de segunda ordem ali) tá tudo na base de estruturas de repetição e dados "mutáveis" (tecnicamente é tudo persistente, mas no código e em efeito parece que é mutável).

A implementação estruturada é estruturada num sentido meio técnico, evitei até usar break. Mas pelo menos acho que não tem muito o que dizer que não tá imperativo e/ou estruturado ali.

O legal de usar Lean é que consegui provar que a função de gostos das crianças tá correta (aqui) usando as informações do enunciado como axiomas, e que o programa funcional gera a saída certa (aqui; só provei pro funcional porque é o mais passível desse tipo de demonstração, os outros ia ser zoadão de provar, com as mônadas espalhadas em todo lugar; ao mesmo tempo, é só comparar a saída com a do funcional hehe).

Só tive que presumir uma informação adicional, que tá meio implícita no enunciado: cada criança termina a brincadeira com exatamente um brinquedo (e todo brinquedo vai parar na mão de alguma criança). Sem essa hipótese não dá pra provar as coisas por exclusão, e aí quebra um pouco as pernas.

De toda forma, maneiro o evento, valeu cenourão \o

Terminei de avaliar sua solução. Testei os 3 paradigmas e todos eles funcionaram. Custei um pouco pra entender que o lake demora alguns minutos pra cada compilação porque ele só mostra o feedback na primeira compilação. A partir da segunda fica só o cursor piscando sem avisar nada. Então pensei que o bicho tinha bugado de vez e acabei reinstalando o lake diversas vezes achando que era problema dele mesmo. Mas depois descobri que a solução era botar pra rodar, tomar um copo d'água, correr 500m e tomar um banho que o programa terminava de rodar kkkkkkk !!
Isso pq eu rodei no Linux, pq se fosse no Windows estava instalando até hoje pq, provavelmente, eles pediriam para eu encontrar um Sapo violeta chinês no mar vermelho do Havaí cantando "Acordando o prédio" na voz do Luan Santana pra conseguir instalar. No Linux é só rodar o cURL e ser feliz.

Depois de toda essa aventura, após rodar e avaliar a solução, venho concluir que é PONTO PRO MASCARADO! 🎉🎊
Neste caso, como vc solucionou em 3 paradigmas diferentes, mesmo usando uma única linguagem, vc recebe a medalha, os 100 Bravecoins que já ganharia mesmo, +150 Bravecoins (50 de cada solução) e o bônus de +50 por resolver nos 3 paradigmas.




Parece que o sistema estava fortemente acoplado para que a criança recebesse somente um brinquedo (isso vc até justificou no tópico) e, por isso, não consegui botar na caixinha de areia pra fazer a bagunça. Mas, de toda forma, o mesmo desafio proposto para a May vale para vc tbm. Você pode refatorar a solução para que aceite vários brinquedos, sem se importar com o que há dentro da caixa.
 
Aqui está a resolução do meu código, fiz na gambiarra, mas espero que esteja certo.

Sua solução já foi avaliada e submetida aos testes. Logo tenho o meu veredito.
O resultado saiu certo, mas ao olhar o código, vc não fez o algoritmo dos brinquedos sendo distribuídos para cada criança de acordo com a brincadeira descrita no enunciado. O que vc fez, na verdade, foi o código para associar qual brinquedo cada criança gosta, apenas. E não é isso que enunciado pede.
Como disse no vídeo, essa parte não precisa ser feita em código, vc já pode associar o brinquedo para a criança no momento da declaração. Daí o que precisava ser feito, na verdade, é a distribuição dos brinquedos passados de mão em mão até chegar na mão da criança que gosta do brinquedo que você já associou anteriormente.

Pense que tem uma caixa com vários brinquedos, a primeira criança pega o brinquedo e avalia se ela gosta ou não baseando-se no você já descobriu nas 5 afirmações do enunciado (lembrando: essa associação não é feita em código, já será determinada antes de iniciar o algoritmo).

Vc pode corrigir sua solução desenvolvendo o algoritmo da distribuição dos brinquedos. Os brinquedos que cada criança gosta você já sabe, agora é só fazer a lógica da distribuição dos brinquedos saindo da caixa e sendo passados para as crianças.



Além disso, coloquei o seu programa no meu ambiente de testes e tivemos o resultado, que você pode acessar aqui.
Dos 50 testes, passaram somente 2: A Caixa #1, que é a caixa com um brinquedo cada e a Caixa #13, que é a caixa vazia
A lista das caixas pode te ajudar a fazer os testes com cada caixa diferente.

Você ainda tem chance de ganhar as recompensas fazendo a correção até o final do mês.
 
Opa! Vim deixar aqui minha entrega. Nos últimos meses, tenho estado aos poucos mergulhando na programação com Ruby, nada sério, só para me divertir no RPG Maker, hehe. Decidi colocar minhas habilidades à prova. Então, espero que esteja tudo certo, kkkk.
De todos os participantes, você foi o que melhor entendeu a proposta do desafio. Teve todo o cuidado de usar os pormenores do enunciado.
Botei seu programa à prova de fogo contra 50 caixas diferentes para ver se os resultados são esperados. Infelizmente seu programa só passou de 2/50 testes, no mesmo caso do Samuel. Acesse os relatórios dos seu programa aqui.
Antes disso, precisei alterar as linhas 13 e 15 de #{toy} para #{toy.name} só pra aparecer o nome do brinquedo bonitinho ao invés do endereço da instância e também para o array toys receber uma lista de brinquedos lidos de uma arquivo de texto separado por linhas, onde você pode consultar a lista destes arquivos aqui.

Aqui a solução é bem tranquila. Está no array kids. Ao invés da propriedade favorite_toy da classe Kid aceitar uma instância de Toy, pode ser o nome do brinquedo apenas em forma de string. Daí você compara o nome do brinquedo recebido com o nome do brinquedo favorito para saber qual é o brinquedo favorito.
Ao notar nos resultados, podemos ver que a criança só pega o brinquedo favorito na primeira vez. Na segunda vez que o brinquedo chega de novo, ela não aceita mais e todos acabam descartando o brinquedo. Isso aconteceu justamente porque o brinquedo favorito foi aceitada como uma instância, ou seja, o que está sendo comparado ali não é o nome do brinquedo, mas sim da referência do endereço dele na memória.

Você ainda tem chance de ganhar se corrigir o código até o final do mês.
 
Custei um pouco pra entender que o lake demora alguns minutos pra cada compilação porque ele só mostra o feedback na primeira compilação. A partir da segunda fica só o cursor piscando sem avisar nada. Então pensei que o bicho tinha bugado de vez e acabei reinstalando o lake diversas vezes achando que era problema dele mesmo. Mas depois descobri que a solução era botar pra rodar, tomar um copo d'água, correr 500m e tomar um banho que o programa terminava de rodar kkkkkkk !!
Isso pq eu rodei no Linux, pq se fosse no Windows estava instalando até hoje pq, provavelmente, eles pediriam para eu encontrar um Sapo violeta chinês no mar vermelho do Havaí cantando "Acordando o prédio" na voz do Luan Santana pra conseguir instalar. No Linux é só rodar o cURL e ser feliz.
É, realmente o negócio é meio pesado x)
Duro que ele compila uma pancada de coisa da Mathlib, que tem toda uma bagagem enorme de teoria. Se abrir os logs de compilação dele tem 3k+ arquivos ali, e a maioria é relativamente grandinho kk

Instalar essas coisas no Windows de fato é uma missão impossível. Se tiver um instaladorzinho, estilo Python e Node, até vai; no mais, o jeito é usar o WSL haha

Parece que o sistema estava fortemente acoplado para que a criança recebesse somente um brinquedo (isso vc até justificou no tópico)

Mais ou menos, meu ponto era mais que o enunciado não exige, necessariamente, uma relação um-pra-um entre os gostos crianças e os tipos de brinquedos (que foi o que eu assumi ali, pra provar os gostos de cada criança); teoricamente poderia ter mais de um brinquedo de cada tipo na caixa, é só que o programa meio que ignora e finge que tem só um (porque de fato eu não tratei isso, tinha entendido que era um de cada mesmo).

Pra ilustrar, fiz um programinha em Prolog aqui que respeita todas as informações dadas, mas permite cada criança gostar de mais de um brinquedo (e mais de uma criança gostar do mesmo), ou de nenhum:
Código:
%--------------------------------------------------------------------------------------------------
% Definições.
%--------------------------------------------------------------------------------------------------

% Crianças
child(samuel).
child(franklin).
child(hellen).
child(jc).
child(daniel).

% Brinquedos.
toy(aranha).
toy(sapo).
toy(dentadura).
toy(fantasma).
toy(bruxinha).
toy('outro brinquedo').

% Fila
queue([samuel, franklin, hellen, jc, daniel]).
prev(Child, PrevChild) :- queue(Q), nextto(PrevChild, Child, Q).
next(Child, NextChild) :- prev(NextChild, Child).

%--------------------------------------------------------------------------------------------------
% Recebe/não recebe.
%--------------------------------------------------------------------------------------------------

% 5. As Dentaduras sempre serão passadas para todas as crianças.
receives(_, dentadura).

% Uma criança recebe um brinquedo se é a primeira da fila, ou se a criança anterior na fila recebe
% o brinquedo e não gosta dele.
receives(Child, Toy) :-
    child(Child), toy(Toy),
    (
        prev(Child, PrevChild) -> (
            receives(PrevChild, Toy),
            dislikes(PrevChild, Toy)
        );
        true
    ).

% 2. Daniel nunca vai receber Bruxinhas.
never_receives(daniel, bruxinha).

% 4. As outras crianças nunca receberão Sapos de borracha.
never_receives(Child, sapo) :-
    child(Child),
    Child \= samuel.

%--------------------------------------------------------------------------------------------------
% Gosta/não gosta/pode gostar.
%--------------------------------------------------------------------------------------------------

% 1. Hellen gosta de Fantasminhas que brilham no escuro.
likes(hellen, fantasma).

% Se a criança recebe o brinquedo e a próxima nunca recebe, então a criança gosta do brinquedo.
likes(Child, Toy) :-
    receives(Child, Toy),
    next(Child, NextChild),
    never_receives(NextChild, Toy).

% 3. Franklin não gosta de Bruxinhas.
dislikes(franklin, bruxinha).

% Uma criança pode gostar do brinquedo se ela não desgostar do brinquedo, e se nenhuma criança
% depois dela na fila precisa receber o brinquedo.
might_like(Child, Toy) :-
    child(Child), toy(Toy),
    \+ dislikes(Child, Toy),
    queue(Q), nth0(I, Q, Child),
    forall((nth0(J, Q, OtherChild), J > I), \+ receives(OtherChild, Toy)).

%--------------------------------------------------------------------------------------------------
% Simulação da brincadeira.
%--------------------------------------------------------------------------------------------------

take(Child, Toy, Final) :-
    write(Child), write(" pegou "), writeln(Toy),
    Final = Child.

pass(Child, Toy, Final) :-
    next(Child, NextChild) *-> (
        write(Child), write(" passou "), write(Toy), write(" para "), writeln(NextChild),
        pass_around(NextChild, Toy, Final)
    );
    write("ninguém pegou "), writeln(Toy),
    Final = ninguém.

pass_around(Child, Toy, Final) :-
    % Se a criança gosta do brinquedo, ela fica com ele.
    likes(Child, Toy) -> take(Child, Toy, Final);
    % Se ela pode ou não gostar do brinquedo, simula os dois casos.
    might_like(Child, Toy) -> (
        take(Child, Toy, Final);
        pass(Child, Toy, Final)
    );
    % Se ela não gosta do brinquedo, passa pro próximo.
    pass(Child, Toy, Final).

play(Toy, Final) :- pass_around(samuel, Toy, Final).

:- initialization(main).
main :-
    forall(toy(Toy), (
        write("["), write(Toy), writeln("]"),
        forall(play(Toy, Final), (
            write(Toy), write(" fica com "), writeln(Final), nl)))).

Com esse programa aí dá pra ver que tem ambiguidade nos gostos das crianças; em particular:
Código:
?- forall(might_like(C, T), (write(C), write(" pode gostar de "), writeln(T))).
samuel pode gostar de aranha
samuel pode gostar de sapo
samuel pode gostar de fantasma
samuel pode gostar de bruxinha
samuel pode gostar de outro brinquedo
franklin pode gostar de aranha
franklin pode gostar de sapo
franklin pode gostar de fantasma
franklin pode gostar de outro brinquedo
hellen pode gostar de aranha
hellen pode gostar de sapo
hellen pode gostar de fantasma
hellen pode gostar de bruxinha
hellen pode gostar de outro brinquedo
jc pode gostar de aranha
jc pode gostar de sapo
jc pode gostar de fantasma
jc pode gostar de bruxinha
jc pode gostar de outro brinquedo
daniel pode gostar de aranha
daniel pode gostar de sapo
daniel pode gostar de dentadura
daniel pode gostar de fantasma
daniel pode gostar de bruxinha
daniel pode gostar de outro brinquedo
true.

A query mostra todos os brinquedos que cada criança pode gostar. Claro, tem alguns brinquedos que algumas crianças tem que gostar:
Código:
?- forall(likes(C, T), (write(C), write(" deve gostar de "), writeln(T))).
hellen deve gostar de fantasma
samuel deve gostar de sapo
true.

E alguns que elas não podem gostar:
Código:
?- forall((child(C), toy(T), \+ might_like(C, T)), (write(C), write(" não pode gostar de "), writeln(T))).
samuel não pode gostar de dentadura
franklin não pode gostar de dentadura
franklin não pode gostar de bruxinha
hellen não pode gostar de dentadura
jc não pode gostar de dentadura
true.

Mas fora esses casos, as crianças podem não gostar de nenhum brinquedo, gostar de vários, etc..

Se puder assumir a correspondência um-pra-um, i.e. que dá pra inferir os brinquedos do Franklin, JC e Daniel por eliminação, então esse código aqui completa o predicado likes, ajusta o dislikes, e valida as condições de coerência pra tudo, e aí a saída é equivalente à do programa em Lean:
Código:
    % Descobre os gostos do franklin, jc e daniel.
    forall(member(C, [franklin, jc, daniel]),
        (
            might_like(C, T),
            \+ likes(_, T), T \= 'outro brinquedo',
            asserta(likes(C, T))
        )
    ),

    forall(child(C), (asserta(dislikes(C, T) :- \+ likes(C, T)))),

    % Valida coerência dos gostos.
    \+ (likes(C, T), \+ might_like(C, T)),
    \+ (likes(C1, T), likes(C2, T), C1 \= C2),
    \+ (likes(C, T1), likes(C, T2), T1 \= T2),

    % Valida coerência da condição de receber ou não um brinquedo.
    \+ (receives(C, T), never_receives(C, T))

De toda forma, esse programinha aí dá todas as possibilidades válidas de atribuição de brinquedo por criança, acho que tá valendo (e fica aí a solução implementada mais um paradigma de programação, hehe).

EDIT: Usei SWI-Prolog, tem o https://swish.swi-prolog.org/ que roda online se não quiser instalar (embora provavelmente seja mais tranquilo que Lean hehe), é meio lentinho mas funciona (exceto o asserta, infelizmente) hehe
 
Última edição:
É, realmente o negócio é meio pesado x)
Duro que ele compila uma pancada de coisa da Mathlib, que tem toda uma bagagem enorme de teoria. Se abrir os logs de compilação dele tem 3k+ arquivos ali, e a maioria é relativamente grandinho kk

Instalar essas coisas no Windows de fato é uma missão impossível. Se tiver um instaladorzinho, estilo Python e Node, até vai; no mais, o jeito é usar o WSL haha



Mais ou menos, meu ponto era mais que o enunciado não exige, necessariamente, uma relação um-pra-um entre os gostos crianças e os tipos de brinquedos (que foi o que eu assumi ali, pra provar os gostos de cada criança); teoricamente poderia ter mais de um brinquedo de cada tipo na caixa, é só que o programa meio que ignora e finge que tem só um (porque de fato eu não tratei isso, tinha entendido que era um de cada mesmo).

Pra ilustrar, fiz um programinha em Prolog aqui que respeita todas as informações dadas, mas permite cada criança gostar de mais de um brinquedo (e mais de uma criança gostar do mesmo), ou de nenhum:
Código:
%--------------------------------------------------------------------------------------------------
% Definições.
%--------------------------------------------------------------------------------------------------

% Crianças
child(samuel).
child(franklin).
child(hellen).
child(jc).
child(daniel).

% Brinquedos.
toy(aranha).
toy(sapo).
toy(dentadura).
toy(fantasma).
toy(bruxinha).
toy('outro brinquedo').

% Fila
queue([samuel, franklin, hellen, jc, daniel]).
prev(Child, PrevChild) :- queue(Q), nextto(PrevChild, Child, Q).
next(Child, NextChild) :- prev(NextChild, Child).

%--------------------------------------------------------------------------------------------------
% Recebe/não recebe.
%--------------------------------------------------------------------------------------------------

% 5. As Dentaduras sempre serão passadas para todas as crianças.
receives(_, dentadura).

% Uma criança recebe um brinquedo se é a primeira da fila, ou se a criança anterior na fila recebe
% o brinquedo e não gosta dele.
receives(Child, Toy) :-
    child(Child), toy(Toy),
    (
        prev(Child, PrevChild) -> (
            receives(PrevChild, Toy),
            dislikes(PrevChild, Toy)
        );
        true
    ).

% 2. Daniel nunca vai receber Bruxinhas.
never_receives(daniel, bruxinha).

% 4. As outras crianças nunca receberão Sapos de borracha.
never_receives(Child, sapo) :-
    child(Child),
    Child \= samuel.

%--------------------------------------------------------------------------------------------------
% Gosta/não gosta/pode gostar.
%--------------------------------------------------------------------------------------------------

% 1. Hellen gosta de Fantasminhas que brilham no escuro.
likes(hellen, fantasma).

% Se a criança recebe o brinquedo e a próxima nunca recebe, então a criança gosta do brinquedo.
likes(Child, Toy) :-
    receives(Child, Toy),
    next(Child, NextChild),
    never_receives(NextChild, Toy).

% 3. Franklin não gosta de Bruxinhas.
dislikes(franklin, bruxinha).

% Uma criança pode gostar do brinquedo se ela não desgostar do brinquedo, e se nenhuma criança
% depois dela na fila precisa receber o brinquedo.
might_like(Child, Toy) :-
    child(Child), toy(Toy),
    \+ dislikes(Child, Toy),
    queue(Q), nth0(I, Q, Child),
    forall((nth0(J, Q, OtherChild), J > I), \+ receives(OtherChild, Toy)).

%--------------------------------------------------------------------------------------------------
% Simulação da brincadeira.
%--------------------------------------------------------------------------------------------------

take(Child, Toy, Final) :-
    write(Child), write(" pegou "), writeln(Toy),
    Final = Child.

pass(Child, Toy, Final) :-
    next(Child, NextChild) *-> (
        write(Child), write(" passou "), write(Toy), write(" para "), writeln(NextChild),
        pass_around(NextChild, Toy, Final)
    );
    write("ninguém pegou "), writeln(Toy),
    Final = ninguém.

pass_around(Child, Toy, Final) :-
    % Se a criança gosta do brinquedo, ela fica com ele.
    likes(Child, Toy) -> take(Child, Toy, Final);
    % Se ela pode ou não gostar do brinquedo, simula os dois casos.
    might_like(Child, Toy) -> (
        take(Child, Toy, Final);
        pass(Child, Toy, Final)
    );
    % Se ela não gosta do brinquedo, passa pro próximo.
    pass(Child, Toy, Final).

play(Toy, Final) :- pass_around(samuel, Toy, Final).

:- initialization(main).
main :-
    forall(toy(Toy), (
        write("["), write(Toy), writeln("]"),
        forall(play(Toy, Final), (
            write(Toy), write(" fica com "), writeln(Final), nl)))).

Com esse programa aí dá pra ver que tem ambiguidade nos gostos das crianças; em particular:
Código:
?- forall(might_like(C, T), (write(C), write(" pode gostar de "), writeln(T))).
samuel pode gostar de aranha
samuel pode gostar de sapo
samuel pode gostar de fantasma
samuel pode gostar de bruxinha
samuel pode gostar de outro brinquedo
franklin pode gostar de aranha
franklin pode gostar de sapo
franklin pode gostar de fantasma
franklin pode gostar de outro brinquedo
hellen pode gostar de aranha
hellen pode gostar de sapo
hellen pode gostar de fantasma
hellen pode gostar de bruxinha
hellen pode gostar de outro brinquedo
jc pode gostar de aranha
jc pode gostar de sapo
jc pode gostar de fantasma
jc pode gostar de bruxinha
jc pode gostar de outro brinquedo
daniel pode gostar de aranha
daniel pode gostar de sapo
daniel pode gostar de dentadura
daniel pode gostar de fantasma
daniel pode gostar de bruxinha
daniel pode gostar de outro brinquedo
true.

A query mostra todos os brinquedos que cada criança pode gostar. Claro, tem alguns brinquedos que algumas crianças tem que gostar:
Código:
?- forall(likes(C, T), (write(C), write(" deve gostar de "), writeln(T))).
hellen deve gostar de fantasma
samuel deve gostar de sapo
true.

E alguns que elas não podem gostar:
Código:
?- forall((child(C), toy(T), \+ might_like(C, T)), (write(C), write(" não pode gostar de "), writeln(T))).
samuel não pode gostar de dentadura
franklin não pode gostar de dentadura
franklin não pode gostar de bruxinha
hellen não pode gostar de dentadura
jc não pode gostar de dentadura
true.

Mas fora esses casos, as crianças podem não gostar de nenhum brinquedo, gostar de vários, etc..

Se puder assumir a correspondência um-pra-um, i.e. que dá pra inferir os brinquedos do Franklin, JC e Daniel por eliminação, então esse código aqui completa o predicado likes, ajusta o dislikes, e valida as condições de coerência pra tudo, e aí a saída é equivalente à do programa em Lean:
Código:
    % Descobre os gostos do franklin, jc e daniel.
    forall(member(C, [franklin, jc, daniel]),
        (
            might_like(C, T),
            \+ likes(_, T), T \= 'outro brinquedo',
            asserta(likes(C, T))
        )
    ),

    forall(child(C), (asserta(dislikes(C, T) :- \+ likes(C, T)))),

    % Valida coerência dos gostos.
    \+ (likes(C, T), \+ might_like(C, T)),
    \+ (likes(C1, T), likes(C2, T), C1 \= C2),
    \+ (likes(C, T1), likes(C, T2), T1 \= T2),

    % Valida coerência da condição de receber ou não um brinquedo.
    \+ (receives(C, T), never_receives(C, T))

De toda forma, esse programinha aí dá todas as possibilidades válidas de atribuição de brinquedo por criança, acho que tá valendo (e fica aí a solução implementada mais um paradigma de programação, hehe).

EDIT: Usei SWI-Prolog, tem o https://swish.swi-prolog.org/ que roda online se não quiser instalar (embora provavelmente seja mais tranquilo que Lean hehe), é meio lentinho mas funciona (exceto o asserta, infelizmente) hehe
Chique!
Você recebeu +200 Bravecoins como gratificação por refatorar a solução. Já está na conta. :cool:
 
Muito bem, pessoal!
O evento CÓDIGO MALDITO encerrou-se.
Muito Obrigado a todos que participaram!

Abaixo, vou disponibilizar o repositório com as soluções do desafio.

Também podemos conferir o desenvolvimento das soluções que fiz ao vivo no meu canal:
(foi dividido em duas partes porque a live caiu, como de praxe ._.)

Nos vemos no próximo evento!
 
Estado
Tópico fechado. Não é possível fazer postagens nela.
Voltar
Topo