%%% ---------------------------------------------------------------------------- %%% pascaltriangle: Typeset Pascal triangle figure with LaTeX3 %%% Author : Nan Geng <nangeng@nwafu.edu.cn> %%% Repository: https://github.com/registor/pascaltriangle or https://gitee.com/nwafu_nan/pascaltriangle %%% License : The LaTeX Project Public License 1.3c %%% ---------------------------------------------------------------------------- \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \ProvidesExplPackage{pascaltriangle}{2022-01-28}{v1.0.1} {Typeset Pascal triangle figure with LaTeX3} \RequirePackage{xparse} %% \tl_if_eq:NnTF 与texlive 2020的兼容性设置 \cs_if_exist:NF \tl_if_eq:NnTF { \tl_new:N \l__tblr_backport_b_tl \prg_new_protected_conditional:Npnn \tl_if_eq:Nn #1 #2 { T, F, TF } { \group_begin: \tl_set:Nn \l__tblr_backport_b_tl {#2} \exp_after:wN \group_end: \if_meaning:w #1 \l__tblr_backport_b_tl \prg_return_true: \else: \prg_return_false: \fi: } \prg_generate_conditional_variant:Nnn \tl_if_eq:Nn { c } { TF, T, F } } \cs_if_exist:NF \seq_map_indexed_function:NN { \cs_set_eq:NN \seq_map_indexed_function:NN \seq_indexed_map_function:NN } %% 解决TikZåº“æ— æ³•åœ¨Expl3ä¸è½½å…¥é—®é¢˜ \RequirePackage {amsmath, tikz, etoolbox} \ExplSyntaxOff \patchcmd {\tcb@input@library@in} {% \input\tcbpkgprefix#1\relax% } {% \@pushfilename \input\tcbpkgprefix#1\relax% \@popfilename } {}{} \patchcmd {\pgfutil@InputIfFileExists} {\input #1} {% \@pushfilename \xdef\@currname{#1}% \input #1 % \@popfilename } {}{} \ExplSyntaxOn \usetikzlibrary{shapes.geometric} %% 定义å˜é‡ \bool_new:N \l__pascal_num_cell_bool % 是å¦ç»˜åˆ¶è¡Œåˆ—å· \bool_new:N \l__pascal_binom_cell_bool % 是å¦ä»…绘制二项å¼è¡¨è¾¾å¼ \tl_new:N \l__pascal_cell_color_tl % å•å…ƒæ ¼å¡«å……é¢œè‰² \tl_new:N \l__pascal_shift_col_pt_tl % åˆ—å˜æ¢åæ ‡ \tl_new:N \l__pascal_shift_row_pt_tl % è¡Œå˜æ¢åæ ‡ \tl_new:N \l__pascal_font_size_tl % æ–‡ä»¶å¤§å° \int_new:N \l__pascal_shape_type_int % 形状(1---ç‰è…°ï¼Œ2---ç›´è§’) \int_new:N \l__pascal_row_idx_int % 行索引(从0计数) \int_new:N \l__pascal_col_idx_int % 列索引(从0计数) \int_new:N \l__pascal_row_top_int % å„列最大行数 \int_new:N \l__pascal_total_idx_int % 索引总数 \int_new:N \l__pascal_fill_row_int % 填充行å·(最大值与当å‰åˆ—数有关,从顶å‘下从0计数) \int_new:N \l__pascal_fill_col_int % 填充列å·(从0计数) \dim_new:N \l__pascal_cell_radius_dim % å•å…ƒæ ¼å¤§å°(ä¸å¿ƒåˆ°é¡¶ç‚¹çš„åŠå¾„) %% 选项设计 \keys_define:nn { pascal } { % 是å¦éœ€è¦è¡Œåˆ—ç¼–å· withnum .bool_set:N = \l__pascal_num_cell_bool, withnum .default:n = true, withnum .initial:n = false, % 是å¦ä»…绘制二项å¼è¡¨è¾¾å¼ binom .bool_set:N = \l__pascal_binom_cell_bool, binom .default:n = true, binom .initial:n = false, % 形状选择(iso---ç‰è…°ä¸‰è§’å½¢, rt---直角三角形) shape .choice:, shape .value_required:n = true, shape .choices:nn = { iso, rt } { \int_set_eq:NN \l__pascal_shape_type_int \l_keys_choice_int }, shape .initial:n = iso, % å•å…ƒæ ¼åŠå¾„(ä¸å¿ƒåˆ°é¡¶ç‚¹) radius .dim_set:N = \l__pascal_cell_radius_dim, radius .initial:n = 0.5cm, % æ–‡å—å¤§å° fontsize .tl_set:N = \l__pascal_font_size_tl, fontsize .initial:n = \small, % è¦å¡«å……å•å…ƒæ ¼è¡Œæ•°(按列从顶å‘下,从0开始计数) fillr .int_set:N = \l__pascal_fill_row_int, fillr .initial:n = 1 , % è¦å¡«å……å•å…ƒæ ¼åˆ—æ•°(从左å‘å³ï¼Œä»Ž0开始计数) fillc .int_set:N = \l__pascal_fill_col_int, fillc .initial:n = 1 , fillrc .meta:n = { fillr = #1 , fillc = #1 }, unknown .code:n = { \__pascal_error:n { unknown-option } } } \msg_new:nnn { pascal } { unknown-option } { package~ option~ "\l_keys_key_tl"~ is~ unknown. } %% 傿•°è®¾ç½®ç”¨æˆ·æŽ¥å£ \NewDocumentCommand \pascalset { m } { \keys_set:nn { pascal } {#1} } %% 利用LaTeX3çš„facté˜¶ä¹˜è®¡ç®—å‡½æ•°è®¡ç®—ç»„åˆæ•° \cs_set:Npn \__pascal_binomcoeff:nn #1#2 { \fp_eval:n { fact(#1) / (fact(#2) * fact(#1 - #2)) } } %% ç»„åˆæ•°è®¡ç®—ç”¨æˆ·æŽ¥å£ \NewDocumentCommand{\binomc}{m m} { \__pascal_binomcoeff:nn{#1}{#2} } %% 绘制Pascal三角形 %% 注æ„":"æ— æ³•ä½¿ç”¨é€ æˆæžåæ ‡ä¸èƒ½ç”¨çš„问题,以下网站给出了解决方案 %% https://tex.stackexchange.com/questions/501333/how-to-use-colon-as-part-of-tikz-syntax-while-in-explsyntaxon-environment %% å°†":"用\c_colon_str代替 %% æ ¹æ®å½¢çŠ¶ç±»åž‹è®¡ç®—åˆ—å˜æ¢åæ ‡(æžåæ ‡) \cs_set:Npn \__pascal_shift_col_pt:n #1 { \int_case:nn { \l__pascal_shape_type_int } { {1}{ \tl_set:Nn \l__pascal_shift_col_pt_tl { -60 \c_colon_str \fp_eval:n {sqrt(3) * \l__pascal_cell_radius_dim * #1}pt } } {2}{ \tl_set:Nn \l__pascal_shift_col_pt_tl { -45 \c_colon_str \fp_eval:n {2 * \l__pascal_cell_radius_dim * #1}pt } } } } %% æ ¹æ®å½¢çŠ¶ç±»åž‹è®¡ç®—è¡Œå˜æ¢åæ ‡(æžåæ ‡) \cs_set:Npn \__pascal_shift_row_pt:n #1 { \int_case:nn { \l__pascal_shape_type_int } { {1}{ \tl_set:Nn \l__pascal_shift_row_pt_tl { -120 \c_colon_str \fp_eval:n {sqrt(3) * \l__pascal_cell_radius_dim * #1}pt } } {2}{ \tl_set:Nn \l__pascal_shift_row_pt_tl { -90 \c_colon_str \fp_eval:n {sqrt(2) * \l__pascal_cell_radius_dim * #1}pt } } } } %% æ£å…边形é—åˆè·¯å¾„代ç \cs_set:Npn \__pascal_hex_cell: { (30 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (90 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (150 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (210 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (270 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (330 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- cycle (90 \c_colon_str 0) } %% æ£æ–¹å½¢é—åˆè·¯å¾„代ç \cs_set:Npn \__pascal_square_cell: { (45 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (134 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (225 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- (-45 \c_colon_str \fp_eval:n{\l__pascal_cell_radius_dim}pt) -- cycle (90 \c_colon_str 0) } %% ç»˜åˆ¶è¡Œåˆ—ç¼–å·æ ‡è®°å•å…ƒæ ¼ \cs_set:Npn \__pascal_num_draw:nnn #1#2#3 { \int_case:nn { \l__pascal_shape_type_int } { {1}{% æ£å…边形 \int_compare:nNnT { #1 } = {0}% 最左列 { \int_compare:nNnT { #2 } = { #3 - 1 }% 最底行 { \begin{scope}[shift={(-150\c_colon_str {\fp_eval:n{3*\l__pascal_cell_radius_dim}pt})}] \draw[dashed, top~color=gray!10,bottom~color=gray!20] \__pascal_hex_cell: node[rotate=-45] {$m,n$}; \end{scope} } } \int_compare:nNnT { #1 } = { 0 }% 最左列 { \begin{scope}[shift={(-180\c_colon_str {\fp_eval:n{sqrt(3)*\l__pascal_cell_radius_dim}pt})}] \draw[dashed, top~color=gray!10,bottom~color=gray!20] \__pascal_hex_cell: node{$(\int_eval:n {#2})$}; \end{scope} } \int_compare:nNnT { #2 } = { #3 - 1 }% 最底行 { \begin{scope}[shift={(-120\c_colon_str {\fp_eval:n{sqrt(3)*\l__pascal_cell_radius_dim}pt})}] \draw[dashed, top~color=gray!10,bottom~color=gray!20] \__pascal_hex_cell: node {$(\int_eval:n {#1})$}; \end{scope} } } {2}{% æ£æ–¹å½¢ \int_compare:nNnT { #1 } = {0}% 最左列 { \int_compare:nNnT { #2 } = { #3 - 1 }% 最底行 { \begin{scope}[shift={(-135\c_colon_str {\fp_eval:n{2*\l__pascal_cell_radius_dim}pt})}] \draw[dashed, top~color=gray!10,bottom~color=gray!20] \__pascal_square_cell: node[scale=0.8,rotate=-45] {$m,n$}; \end{scope} } } \int_compare:nNnT { #1 } = { 0 }% 最左列 { \begin{scope}[shift={(-180\c_colon_str {\fp_eval:n{sqrt(2)*\l__pascal_cell_radius_dim}pt})}] \draw[dashed, top~color=gray!10,bottom~color=gray!20] \__pascal_square_cell: node{$(\int_eval:n {#2})$}; \end{scope} } \int_compare:nNnT { #2 } = { #3 - 1 }% 最底行 { \begin{scope}[shift={(-90\c_colon_str {\fp_eval:n{sqrt(2)*\l__pascal_cell_radius_dim}pt})}] \draw[dashed, top~color=gray!10,bottom~color=gray!20] \__pascal_square_cell: node {$(\int_eval:n {#1})$}; \end{scope} } } } } %% 绘制三角形å•å…ƒæ ¼ \cs_set:Npn \__pascal_cell_draw:nn #1#2 { \int_case:nn { \l__pascal_shape_type_int } { {1}{% æ£å…边形 \draw[top~color=\l__pascal_cell_color_tl!20,bottom~color=\l__pascal_cell_color_tl!60] \__pascal_hex_cell: \bool_if:NTF \l__pascal_binom_cell_bool { node {$\binom{\int_eval:n {#1}}{\int_eval:n {#2}}$}; } { node {$\__pascal_binomcoeff:nn {#1}{#2}$}; } } {2}{% æ£æ–¹å½¢ \draw[top~color=\l__pascal_cell_color_tl!20,bottom~color=\l__pascal_cell_color_tl!60] \__pascal_square_cell: \bool_if:NTF \l__pascal_binom_cell_bool { node {$\binom{\int_eval:n {#1}}{\int_eval:n {#2}}$}; } { node {$\__pascal_binomcoeff:nn {#1}{#2}$}; } } } } %% 绘制Pascal三角形 % ç‰è…°ä¸‰è§’形的绘制原ç†å‚考了 https://texample.net/tikz/examples/pascal-triangle/ % Author: M.H. Ahmadi \cs_set:Npn \__pascal_triangle_draw:n #1 { % 设置æ£å¸¸å•å…ƒæ ¼ä¸ºç°è‰² \tl_set:Nn \l__pascal_cell_color_tl {gray} % 记录绘制列数 \int_set:Nn \l_tmpa_int {#1} % 使用TikZ绘制 \begin{tikzpicture}[font=\l__pascal_font_size_tl] % 列循环 \int_step_inline:nn {\l_tmpa_int} { % 调整为从0计数,以便于åŽç»è®¡ç®— \int_set:Nn \l__pascal_col_idx_int { ##1 - 1 } % è®¡ç®—åˆ—å˜æ¢åæ ‡(æžåæ ‡) \__pascal_shift_col_pt:n {\l__pascal_col_idx_int} % 用scopeçŽ¯å¢ƒå˜æ¢å„列到指定ä½ç½® \begin{scope}[shift={(\l__pascal_shift_col_pt_tl)}] % 计算æ¯åˆ—最多行数 \int_set:Nn \l__pascal_row_top_int {\l_tmpa_int - ##1 + 1} % 行循环 \int_step_inline:nn { \l__pascal_row_top_int } { % 调整为从0计数,以便于åŽç»è®¡ç®— \int_set:Nn \l__pascal_row_idx_int { ####1 - 1 } % è®¡ç®—ç»„åˆæ•°è®¡ç®—ä¸çš„行数 \int_zero:N \l__pascal_total_idx_int \int_add:Nn \l__pascal_total_idx_int { \l__pascal_row_idx_int } \int_add:Nn \l__pascal_total_idx_int { \l__pascal_col_idx_int } % 为指定行设置绘制颜色 \int_case:nn { \l__pascal_col_idx_int } { {0}{ \tl_set:Nn \l__pascal_cell_color_tl { pink } } {1}{ \tl_set:Nn \l__pascal_cell_color_tl { yellow } } {2}{ \tl_set:Nn \l__pascal_cell_color_tl { blue } } {3}{ \tl_set:Nn \l__pascal_cell_color_tl { green } } {\l__pascal_fill_col_int - 1}{ \int_compare:nNnTF{\l__pascal_row_idx_int} < { \l__pascal_fill_row_int + 1 } {\tl_set:Nn \l__pascal_cell_color_tl { purple }} {\tl_set:Nn \l__pascal_cell_color_tl { gray }} } {\l__pascal_fill_col_int}{ \int_compare:nNnTF{\l__pascal_row_idx_int} = { \l__pascal_fill_row_int } {\tl_set:Nn \l__pascal_cell_color_tl { purple }} {\tl_set:Nn \l__pascal_cell_color_tl { gray }} } } % è®¡ç®—è¡Œå˜æ¢åæ ‡(æžåæ ‡) \__pascal_shift_row_pt:n {\l__pascal_row_idx_int} % 用scopeçŽ¯å¢ƒå˜æ¢å„行到指定ä½ç½® \begin{scope}[shift={(\l__pascal_shift_row_pt_tl)}] % 是å¦ç»˜åˆ¶è¡Œåˆ—ç¼–å· \bool_if:NT \l__pascal_num_cell_bool { \__pascal_num_draw:nnn { \l__pascal_col_idx_int } { \l__pascal_row_idx_int } { \l__pascal_row_top_int } } % 绘制一个å•å…ƒæ ¼ \__pascal_cell_draw:nn{\l__pascal_total_idx_int}{\l__pascal_col_idx_int} \end{scope} } \end{scope} } \end{tikzpicture} } %% 绘制Pascalä¸‰è§’å½¢ç”¨æˆ·æŽ¥å£ \NewDocumentCommand{\pascal}{O{} m} { \group_begin: \keys_set:nn { pascal } {#1} \__pascal_triangle_draw:n{#2} \group_end: } \endinput