Skip to content

Instantly share code, notes, and snippets.

@zr-tex8r
Last active May 26, 2020 06:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zr-tex8r/255112a682c86a5ff4bb61b1ba99249a to your computer and use it in GitHub Desktop.
Save zr-tex8r/255112a682c86a5ff4bb61b1ba99249a to your computer and use it in GitHub Desktop.
expl3:単価が異なるお菓子をどういう組み合わせで買えば目標の合計値になるか問題
% upLaTeX文書
\documentclass[uplatex,a4paper]{jsarticle}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \l_xx_total_int
\clist_new:N \l_xx_price_clist
\prop_new:N \l_xx_count_prop
\bool_new:N \l_xx_solved_bool
\int_new:N \l_xx_instid_int
\int_new:N \l_xx_size_int
\int_new:N \l_xx_price_int
\NewDocumentCommand \Okashi { m m }
{
\int_set:Nn \l_xx_total_int {#1}
\clist_set:Nn \l_xx_price_clist {#2}
\xx_solve:
\xx_print_solution:n {#1}
}
\cs_new:Nn \xx_print_solution:n
{
\bool_if:NTF \l_xx_solved_bool
{
\int_step_inline:nnn { 1 } { \l_xx_size_int }
{
\prop_get:NnN \l_xx_count_prop {##1} \l_tmpa_tl
\clist_item:Nn \l_xx_price_clist {##1}
円のが \l_tmpa_tl 個
\int_compare:nNnF {##1} = { \l_xx_size_int } { 、 }
}
\int_eval:n {#1}
円になる。
}
{ 解が見つかりません。 }
}
\cs_new:Nn \xx_solve:
{
\int_set:Nn \l_xx_size_int { \clist_count:N \l_xx_price_clist }
\int_step_inline:nnn { 1 } { \l_xx_size_int }
{
\int_add:Nn \l_xx_total_int { - \clist_item:Nn \l_xx_price_clist {##1} }
\prop_put:Nnn \l_xx_count_prop {##1} { 1 }
}
\int_compare:nNnTF { \l_xx_total_int } < { 0 }
{ \bool_set_false:N \l_xx_solved_bool }
{ % always declare a new intarray
\int_incr:N \l_xx_instid_int
\exp_args:Nc \xx_solve_aux:N { g_xx_price_ \int_to_arabic:n { \l_xx_instid_int } _intarray }
}
}
\cs_new:Nn \xx_solve_aux:N
{
\intarray_new:Nn #1 { \l_xx_total_int }
\cs_set:Npn \xx_array_get:n { \intarray_item:Nn #1 }
\cs_set:Npn \xx_array_set:nn { \intarray_gset:Nnn #1 }
\int_step_function:nnN { 1 } { \l_xx_size_int } \xx_one_item:n
\int_compare:nNnTF { \xx_array_get:n {\l_xx_total_int} } = { 0 }
{ \bool_set_false:N \l_xx_solved_bool }
{
\xx_pick_item:
\bool_set_true:N \l_xx_solved_bool
}
}
\cs_new:Nn \xx_one_item:n
{
\int_set:Nn \l_xx_price_int { \clist_item:Nn \l_xx_price_clist {#1} }
\int_step_inline:nnn { \l_xx_price_int } { \l_xx_total_int }
{
\bool_lazy_and:nnT
{ \int_compare_p:nNn { \xx_array_get:n {##1} } = { 0 } }
{
\bool_lazy_or_p:nn % index must not be zero
{ \int_compare_p:nNn { ##1 } = { \l_xx_price_int } }
{ \int_compare_p:nNn { \xx_array_get:n { ##1 - \l_xx_price_int } } > { 0 } }
}
{ \xx_array_set:nn {##1} {#1} }
}
}
\cs_new:Nn \xx_pick_item:
{
\int_do_while:nNnn { \l_xx_total_int } > { 0 }
{
\int_set:Nn \l_tmpa_int { \xx_array_get:n { \l_xx_total_int } }
\int_add:Nn \l_xx_total_int { - \clist_item:Nn \l_xx_price_clist { \l_tmpa_int } }
\prop_get:NVN \l_xx_count_prop \l_tmpa_int \l_tmpa_tl
\int_set:Nn \l_tmpb_int { \l_tmpa_tl + 1 }
\prop_put:NVV \l_xx_count_prop \l_tmpa_int \l_tmpb_int
}
}
\ExplSyntaxOff
\begin{document}
\Okashi{3000}{146,172,400,500}
\Okashi{9731}{146,172,400,500}
%時間かかるけど解けた
%\Okashi{129414}{146,172,400,500}
\end{document}
@zr-tex8r
Copy link
Author

「xpl3のプログラムを読む練習(?)がしたいけど、中のロジックがよくわからん」
という人のために、ほぼ同じ内容をLuaで書いたのを用意した→Lua版

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment