Showing preview only (4,601K chars total). Download the full file or copy to clipboard to get everything.
Repository: trizen/perl-scripts
Branch: master
Commit: 61e3d7fc8407
Files: 1290
Total size: 4.2 MB
Directory structure:
gitextract_4x__q3zn/
├── .gitignore
├── Analyzers/
│ ├── char_counter.pl
│ ├── chr_freq.pl
│ ├── dieharder.pl
│ ├── first_letter_top.pl
│ ├── kcal/
│ │ ├── kcal.pl
│ │ └── products.csv
│ ├── kernel_config_diff.pl
│ ├── perl_code_analyzer.pl
│ ├── perl_code_spellcheck.pl
│ ├── reptop.pl
│ ├── text_stats.pl
│ ├── unidecode_word_top.pl
│ ├── wcer.pl
│ └── word_suffix_top.pl
├── Audio/
│ ├── auto-mp3tags.pl
│ ├── group_audio_files.pl
│ ├── mkv_audio_to_opus.pl
│ ├── recompress_audio_track.pl
│ ├── rem-mp3tags.pl
│ ├── wave-cmp.pl
│ └── wave-cmp2.pl
├── Benchmarks/
│ ├── array_range_vs_shift.pl
│ ├── compression_algorithms.pl
│ ├── json_vs_storable.pl
│ ├── schwartzian_transform.pl
│ └── types_of_variables.pl
├── Book tools/
│ ├── rosettacode_to_markdown.pl
│ └── update_summary.pl
├── Compression/
│ ├── High-level/
│ │ ├── ablz_file_compression.pl
│ │ ├── bbwr_file_compression.pl
│ │ ├── blzss2_file_compression.pl
│ │ ├── blzss_file_compression.pl
│ │ ├── brlzss_file_compression.pl
│ │ ├── bwac_file_compression.pl
│ │ ├── bwad_file_compression.pl
│ │ ├── bwlz2_file_compression.pl
│ │ ├── bwlz3_file_compression.pl
│ │ ├── bwlz_file_compression.pl
│ │ ├── bwlza2_file_compression.pl
│ │ ├── bwlza_file_compression.pl
│ │ ├── bwlzad2_file_compression.pl
│ │ ├── bwlzad_file_compression.pl
│ │ ├── bwlzb_file_compression.pl
│ │ ├── bwlzhd2_file_compression.pl
│ │ ├── bwlzhd_file_compression.pl
│ │ ├── bwlzss_file_compression.pl
│ │ ├── bwrl2_file_compression.pl
│ │ ├── bwrm2_file_compression.pl
│ │ ├── bwrm_file_compression.pl
│ │ ├── bwt2_file_compression.pl
│ │ ├── bwt_file_compression.pl
│ │ ├── bzip2_file_compression.pl
│ │ ├── gzip_file_compression.pl
│ │ ├── hblz_file_compression.pl
│ │ ├── lz255_file_compression.pl
│ │ ├── lz2ss_file_compression.pl
│ │ ├── lz4_file_compression.pl
│ │ ├── lz772_file_compression.pl
│ │ ├── lz77_file_compression.pl
│ │ ├── lz77f_file_compression.pl
│ │ ├── lzac_file_compression.pl
│ │ ├── lzb_file_compression.pl
│ │ ├── lzbbw_file_compression.pl
│ │ ├── lzbf_file_compression.pl
│ │ ├── lzbh_file_compression.pl
│ │ ├── lzbw2_file_compression.pl
│ │ ├── lzbw3_file_compression.pl
│ │ ├── lzbw4_file_compression.pl
│ │ ├── lzbw5_file_compression.pl
│ │ ├── lzbw_file_compression.pl
│ │ ├── lzbwa_file_compression.pl
│ │ ├── lzbwad_file_compression.pl
│ │ ├── lzbwd_file_compression.pl
│ │ ├── lzbwh_file_compression.pl
│ │ ├── lzbws_file_compression.pl
│ │ ├── lzhd2_file_compression.pl
│ │ ├── lzhd_file_compression.pl
│ │ ├── lzih_file_compression.pl
│ │ ├── lzmrl2_file_compression.pl
│ │ ├── lzmrl_file_compression.pl
│ │ ├── lzop_file_compression.pl
│ │ ├── lzsbw_file_compression.pl
│ │ ├── lzss2_file_compression.pl
│ │ ├── lzss77_file_compression.pl
│ │ ├── lzss_file_compression.pl
│ │ ├── lzssf_file_compression.pl
│ │ ├── lzssm_file_compression.pl
│ │ ├── lzw_file_compression.pl
│ │ ├── mblz_file_compression.pl
│ │ ├── mbwr_file_compression.pl
│ │ ├── mrl_file_compression.pl
│ │ ├── mybzip2_file_compression.pl
│ │ ├── mygzip_file_compression.pl
│ │ ├── mygzipf_file_compression.pl
│ │ ├── mylz4_file_compression.pl
│ │ ├── mylz4f_file_compression.pl
│ │ ├── myzlib_file_compression.pl
│ │ ├── rablz_file_compression.pl
│ │ ├── rlzss_file_compression.pl
│ │ ├── sbwt_file_compression.pl
│ │ ├── xz_file_compression.pl
│ │ ├── zlib_file_compression.pl
│ │ └── zstd_file_compression.pl
│ ├── bbwr_file_compression.pl
│ ├── bqof_file_compression.pl
│ ├── bwac_file_compression.pl
│ ├── bwad_file_compression.pl
│ ├── bwaz_file_compression.pl
│ ├── bwlz2_file_compression.pl
│ ├── bwlz_file_compression.pl
│ ├── bwlza2_file_compression.pl
│ ├── bwlza_file_compression.pl
│ ├── bwlzad2_file_compression.pl
│ ├── bwlzad_file_compression.pl
│ ├── bwlzhd_file_compression.pl
│ ├── bwlzss_file_compression.pl
│ ├── bwrl2_file_compression.pl
│ ├── bwrl_file_compression.pl
│ ├── bwrla_file_compression.pl
│ ├── bwrlz2_file_compression.pl
│ ├── bwrlz_file_compression.pl
│ ├── bwrm_file_compression.pl
│ ├── bwt2_file_compression.pl
│ ├── bwt_file_compression.pl
│ ├── bww_file_compression.pl
│ ├── bzip2_compressor.pl
│ ├── bzip2_decompressor.pl
│ ├── bzip2_file_compression.pl
│ ├── compress.pl
│ ├── gzip2_file_compression.pl
│ ├── gzip_block_type_1.pl
│ ├── gzip_block_type_1_huffman_only.pl
│ ├── gzip_block_type_2.pl
│ ├── gzip_block_type_2_huffman_only.pl
│ ├── gzip_block_type_2_simple.pl
│ ├── gzip_comment.pl
│ ├── gzip_decompressor.pl
│ ├── gzip_file_compression.pl
│ ├── gzip_store.pl
│ ├── hfm_file_compression.pl
│ ├── lz4_compressor.pl
│ ├── lz4_decompressor.pl
│ ├── lz4_file_compression.pl
│ ├── lz77_file_compression.pl
│ ├── lza_file_compression.pl
│ ├── lzac_file_compression.pl
│ ├── lzaz_file_compression.pl
│ ├── lzb2_file_compression.pl
│ ├── lzb_file_compression.pl
│ ├── lzbf2_file_compression.pl
│ ├── lzbf_file_compression.pl
│ ├── lzbh_file_compression.pl
│ ├── lzbw_file_compression.pl
│ ├── lzbwa_file_compression.pl
│ ├── lzbwad_file_compression.pl
│ ├── lzbwd_file_compression.pl
│ ├── lzbwh_file_compression.pl
│ ├── lzh_file_compression.pl
│ ├── lzhc_file_compression.pl
│ ├── lzhd_file_compression.pl
│ ├── lzih_file_compression.pl
│ ├── lzsa_file_compression.pl
│ ├── lzsad_file_compression.pl
│ ├── lzsbw_file_compression.pl
│ ├── lzss2_file_compression.pl
│ ├── lzss_file_compression.pl
│ ├── lzssf_file_compression.pl
│ ├── lzsst2_file_compression.pl
│ ├── lzsst_file_compression.pl
│ ├── lzt2_file_compression.pl
│ ├── lzt_file_compression.pl
│ ├── lzw_file_compression.pl
│ ├── mbwr_file_compression.pl
│ ├── mra_file_compression.pl
│ ├── mrh_file_compression.pl
│ ├── mrlz_file_compression.pl
│ ├── ppmh_file_compression.pl
│ ├── qof_file_compression.pl
│ ├── rans_file_compression.pl
│ ├── rlac_file_compression.pl
│ ├── rlh_file_compression.pl
│ ├── tac_file_compression.pl
│ ├── tacc_file_compression.pl
│ ├── test_compressors.pl
│ ├── tzip2_file_compression.pl
│ ├── tzip_file_compression.pl
│ ├── unzip.pl
│ ├── zip.pl
│ ├── zlib_compressor.pl
│ ├── zlib_decompressor.pl
│ └── zlib_file_compression.pl
├── Converters/
│ ├── another_notes_to_markdown.pl
│ ├── another_notes_to_material_notes.pl
│ ├── any_to_3gp.pl
│ ├── ass2srt.pl
│ ├── code2pdf.pl
│ ├── euler2pdf.pl
│ ├── from_hex.pl
│ ├── gdbm_to_berkeley.pl
│ ├── gitbook2pdf.pl
│ ├── gz2xz.pl
│ ├── html2pdf.pl
│ ├── html2pdf_chromium.pl
│ ├── html2text.pl
│ ├── json2csv.pl
│ ├── markdown2pdf.pl
│ ├── markdown2pdf_chromium.pl
│ ├── markdown2text.pl
│ ├── notepadfree_to_txt.pl
│ ├── pod2pdf.pl
│ ├── pod2text.pl
│ ├── recompress.pl
│ ├── unicode2ascii.pl
│ ├── vnt2txt_simple.pl
│ ├── xml2hash.pl
│ ├── xpm_c_to_perl.pl
│ ├── xz2gz.pl
│ ├── zip2tar.pl
│ └── zip2tar_fast.pl
├── Decoders/
│ ├── base64_decoding-tutorial.pl
│ ├── cnp_info.pl
│ └── named_parameters.pl
├── Digest/
│ ├── brute-force_resistant_hashing.pl
│ └── crc32.pl
├── Encoding/
│ ├── adaptive_huffman_coding.pl
│ ├── arithmetic_coding.pl
│ ├── arithmetic_coding_adaptive_contexts_in_fixed_bits.pl
│ ├── arithmetic_coding_adaptive_in_fixed_bits.pl
│ ├── arithmetic_coding_anynum.pl
│ ├── arithmetic_coding_in_fixed_bits.pl
│ ├── arithmetic_coding_mpz.pl
│ ├── ascii_encode_decode.pl
│ ├── binary_arithmetic_coding.pl
│ ├── binary_arithmetic_coding_anynum.pl
│ ├── binary_variable_length_run_encoding.pl
│ ├── binradix_arithmetic_coding.pl
│ ├── binradix_arithmetic_coding_anynum.pl
│ ├── burrows-wheeler_file_transform.pl
│ ├── burrows-wheeler_transform-n-char_generalization.pl
│ ├── burrows-wheeler_transform.pl
│ ├── burrows-wheeler_transform_symbolic.pl
│ ├── delta_encoding_with_double-elias_coding.pl
│ ├── delta_encoding_with_elias_coding.pl
│ ├── delta_encoding_with_unary_coding.pl
│ ├── delta_rle_elias_encoding.pl
│ ├── double-elias_gamma_encoding.pl
│ ├── elias_gamma_encoding.pl
│ ├── eyes_dropper.pl
│ ├── fibonacci_coding.pl
│ ├── huffman_coding.pl
│ ├── int2bytes.pl
│ ├── integers_binary_encoding.pl
│ ├── integers_binary_encoding_with_delta_coding.pl
│ ├── integers_binary_encoding_with_huffman_coding.pl
│ ├── jpeg_transform.pl
│ ├── length_encoder.pl
│ ├── lz77_encoding.pl
│ ├── lz77_encoding_symbolic.pl
│ ├── lzss_encoding.pl
│ ├── lzss_encoding_hash_table.pl
│ ├── lzss_encoding_hash_table_fast.pl
│ ├── lzss_encoding_symbolic.pl
│ ├── lzt-fast.pl
│ ├── lzw_encoding.pl
│ ├── math_expr_encoder.pl
│ ├── move-to-front_transform.pl
│ ├── mtf-delta_encoding.pl
│ ├── png_transform.pl
│ ├── ppm_encoding.pl
│ ├── ppm_encoding_dynamic.pl
│ ├── rANS_encoding.pl
│ ├── rANS_encoding_mpz.pl
│ ├── run_length_with_elias_coding.pl
│ ├── string_to_integer_encoding_based_on_primes.pl
│ ├── swap_transform.pl
│ ├── tlen_encoding.pl
│ └── variable_length_run_encoding.pl
├── Encryption/
│ ├── RSA_encryption.pl
│ ├── age-lf.pl
│ ├── backdoored_rsa_with_x25519.pl
│ ├── cbc+xor_file_encrypter.pl
│ ├── crypt_rsa.pl
│ ├── one-time_pad.pl
│ ├── plage.pl
│ └── simple_XOR_cipher.pl
├── File Readers/
│ ├── ldump
│ ├── multi-file-line-reader.pl
│ ├── n_repeated_lines.pl
│ └── tailz
├── File Workers/
│ ├── arxiv_pdf_renamer.pl
│ ├── auto_extensions.pl
│ ├── collect_gifs.pl
│ ├── collect_videos.pl
│ ├── delete_if_exists.pl
│ ├── dir_file_updater.pl
│ ├── file-mover.pl
│ ├── file_updater.pl
│ ├── filename_cmp_del.pl
│ ├── keep_this_formats.pl
│ ├── make_filenames_portable.pl
│ ├── md5_rename.pl
│ ├── multiple_backups.pl
│ ├── remove_eof_newlines.pl
│ ├── split_to_n_lines.pl
│ ├── sub_renamer.pl
│ ├── timestamp_rename.pl
│ ├── undir.pl
│ └── unidec_renamer.pl
├── Finders/
│ ├── ampath
│ ├── dup_subtr_finder.pl
│ ├── fcheck.pl
│ ├── fdf
│ ├── fdf-attr
│ ├── fdf-filename
│ ├── file_binsearch.pl
│ ├── find_perl_scripts.pl
│ ├── find_similar_filenames.pl
│ ├── find_similar_filenames_unidec.pl
│ ├── fsf.pl
│ ├── fsfn.pl
│ ├── human-like_finder.pl
│ ├── large_file_search.pl
│ ├── locatepm
│ ├── longest_substring.pl
│ ├── mimefind.pl
│ ├── model_matching_system.pl
│ ├── path_diff.pl
│ ├── plocate.pl
│ └── similar_files_levenshtein.pl
├── Formatters/
│ ├── ascii_table_csv.pl
│ ├── file_columner.pl
│ ├── fstab_beautifier.pl
│ ├── js_beautify
│ ├── reformat_literal_perl_strings.pl
│ ├── replace_html_links.pl
│ ├── sort_perl_subroutines.pl
│ └── word_columner.pl
├── GD/
│ ├── AND_sierpinski_triangle.pl
│ ├── LSystem/
│ │ ├── LSystem.pm
│ │ ├── Turtle.pm
│ │ ├── honeycomb.pl
│ │ ├── honeycomb_2.pl
│ │ ├── plant.pl
│ │ ├── plant_2.pl
│ │ ├── plant_3.pl
│ │ ├── sierpinski_triangle.pl
│ │ └── tree.pl
│ ├── XOR_pattern.pl
│ ├── abstract_map.pl
│ ├── barnsley_fern_fractal.pl
│ ├── binary_triangle.pl
│ ├── black_star_turtle.pl
│ ├── black_yellow_number_triangles.pl
│ ├── box_pattern.pl
│ ├── chaos_game_pentagon.pl
│ ├── chaos_game_tetrahedron.pl
│ ├── chaos_game_triangle.pl
│ ├── circular_prime_triangle.pl
│ ├── circular_triangle.pl
│ ├── collatz_triangle.pl
│ ├── color_wheel.pl
│ ├── complex_square.pl
│ ├── congruence_of_squares_triangle.pl
│ ├── cuboid_turtle.pl
│ ├── cuboid_turtle3.pl
│ ├── cuboid_turtle_2.pl
│ ├── dancing_shapes.pl
│ ├── divisor_circles.pl
│ ├── divisor_triangle.pl
│ ├── elementary_cellular_automaton_generalized.pl
│ ├── fact_exp_primorial_growing.pl
│ ├── factor_circles.pl
│ ├── factor_triangle.pl
│ ├── factorial_turtles.pl
│ ├── factors_of_two_triangle.pl
│ ├── farey_turnings_plot.pl
│ ├── fgraph.pl
│ ├── fgraph_precision.pl
│ ├── fibonacci_gd.pl
│ ├── fibonacci_spirals.pl
│ ├── generator_turtle.pl
│ ├── geometric_shapes.pl
│ ├── goldbach_conjecture_possibilities.pl
│ ├── horsie_art.pl
│ ├── julia_set.pl
│ ├── julia_set_complex.pl
│ ├── julia_set_random.pl
│ ├── julia_set_rperl.pl
│ ├── koch_snowflakes.pl
│ ├── langton_s_ant_gd.pl
│ ├── line_pattern_triangles.pl
│ ├── magic_triangle.pl
│ ├── mandelbrot_like_set.pl
│ ├── mandelbrot_like_set_gcomplex.pl
│ ├── mathematical_butt.pl
│ ├── mathematical_shapes.pl
│ ├── mirror_shells.pl
│ ├── moebius_walking_line.pl
│ ├── number_triangles.pl
│ ├── numeric_circles.pl
│ ├── pascal-fibonacci_triangle.pl
│ ├── pascal_powers_of_two_triangle.pl
│ ├── pascal_s_triangle_multiples.pl
│ ├── pascal_special_triangle.pl
│ ├── pattern_triangle.pl
│ ├── peacock_triangles.pl
│ ├── pi_abstract_art.pl
│ ├── pi_turtle.pl
│ ├── prime_consecutive_sums.pl
│ ├── prime_gaps.pl
│ ├── prime_rectangles.pl
│ ├── prime_stripe_triangle.pl
│ ├── prime_triangle_90deg.pl
│ ├── pythagoras_tree.pl
│ ├── random_abstract_art.pl
│ ├── random_abstract_art_2.pl
│ ├── random_langton_s_ant.pl
│ ├── random_looking_pattern_triangle.pl
│ ├── random_machinery_art.pl
│ ├── random_noise_triangle.pl
│ ├── random_turtles.pl
│ ├── real_shell.pl
│ ├── recursive_squares.pl
│ ├── regular_poligons.pl
│ ├── reversed_prime_triangles.pl
│ ├── right_triangle_primes.pl
│ ├── sandpiles.pl
│ ├── sierpinski_fibonacci_triangle.pl
│ ├── sierpinski_triangle.pl
│ ├── spinning_shapes.pl
│ ├── spiral_matrix_primes.pl
│ ├── spiral_tree.pl
│ ├── square_of_circles.pl
│ ├── star_turtle.pl
│ ├── stern_brocot_shapes.pl
│ ├── triangle_factors.pl
│ ├── triangle_primes.pl
│ ├── triangle_primes_2.pl
│ ├── triangle_primes_irregular.pl
│ ├── trizen_fan_turtle.pl
│ ├── trizen_flat_logo.pl
│ ├── trizen_new_logo.pl
│ ├── trizen_old_logo.pl
│ ├── trizen_text_art.pl
│ ├── tupper_s_self-referential_formula.pl
│ ├── wavy_triangle.pl
│ ├── zeta_real_half_terms.pl
│ └── zig-zag_primes.pl
├── GTK+/
│ ├── mouse_position.pl
│ └── tray-file-browser.pl
├── Game solvers/
│ ├── asciiplanes-player-v2.pl
│ ├── asciiplanes-player.pl
│ ├── dice_game_solver.pl
│ ├── peg-solitaire-solver
│ ├── reaction_time_test.pl
│ ├── reflex_sheep_game.pl
│ ├── sudoku_dice_game_solver.pl
│ ├── sudoku_generator.pl
│ ├── sudoku_solver.pl
│ ├── sudoku_solver_backtracking.pl
│ ├── sudoku_solver_iterative.pl
│ ├── sudoku_solver_stack.pl
│ └── visual_memory_test.pl
├── Games/
│ ├── arrow-key_drawer.pl
│ ├── asciiplanes
│ └── snake_game.pl
├── Generators/
│ ├── bernoulli_numbers_formulas.pl
│ ├── faulhaber_s_formula_symbolic.pl
│ ├── faulhaber_s_formulas_expanded.pl
│ ├── faulhaber_s_formulas_expanded_2.pl
│ ├── faulhaber_s_formulas_generator.pl
│ ├── parsing_and_code_gen.pl
│ ├── powers_of_factorial.pl
│ ├── random_lsystem_generator.pl
│ ├── semiprime_equationization_C_generator.pl
│ ├── semiprime_equationization_Perl_generator.pl
│ └── zeta_2n_generator.pl
├── Greppers/
│ ├── marif
│ ├── mime_types.pl
│ ├── mp3grep.pl
│ ├── scgrep
│ └── unigrep.pl
├── HAL/
│ ├── HAL3736/
│ │ ├── HAL3736.memory
│ │ └── HAL3736.pl
│ ├── HAL8212/
│ │ ├── HAL8212.memory
│ │ └── HAL8212.pl
│ └── HAL9000/
│ ├── HAL9000.memory
│ └── HAL9000.pl
├── Image/
│ ├── 2x_zoom.pl
│ ├── add_exif_info.pl
│ ├── bitmap_monochrome_encoding_decoding.pl
│ ├── bwt_horizontal_transform.pl
│ ├── bwt_rgb_horizontal_transform.pl
│ ├── bwt_rgb_vertical_transform.pl
│ ├── bwt_vertical_transform.pl
│ ├── collage.pl
│ ├── complex_transform.pl
│ ├── cyan_vision.pl
│ ├── darken_image.pl
│ ├── diff_negative.pl
│ ├── edge_detector.pl
│ ├── extract_jpegs.pl
│ ├── fractal_frame.pl
│ ├── fractal_frame_transparent.pl
│ ├── gd_png2jpg.pl
│ ├── gd_similar_images.pl
│ ├── gd_star_trails.pl
│ ├── gif2webp.pl
│ ├── horizontal_scrambler.pl
│ ├── image-hard-rotate.pl
│ ├── image-unpack.pl
│ ├── image2ascii.pl
│ ├── image2audio.pl
│ ├── image2digits.pl
│ ├── image2html.pl
│ ├── image2matrix.pl
│ ├── image2mozaic.pl
│ ├── image2png.pl
│ ├── image2prime.pl
│ ├── image_metadata_clone.pl
│ ├── imager_similar_images.pl
│ ├── img-autocrop-avg.pl
│ ├── img-autocrop-whitebg.pl
│ ├── img-autocrop.pl
│ ├── img_composition.pl
│ ├── img_rewrite.pl
│ ├── julia_transform.pl
│ ├── lookalike_images.pl
│ ├── magick_png2jpg.pl
│ ├── magick_similar_images.pl
│ ├── magick_star_trails.pl
│ ├── matrix_visual.pl
│ ├── mirror_images.pl
│ ├── mtf_horizontal_transform.pl
│ ├── mtf_vertical_transform.pl
│ ├── nearest_neighbor_interpolation.pl
│ ├── optimize_images.pl
│ ├── optimize_images_littleutils.pl
│ ├── outguess-png-imager.pl
│ ├── outguess-png.pl
│ ├── photo_mosaic_from_images.pl
│ ├── qhi_decoder.pl
│ ├── qhi_encoder.pl
│ ├── qoi_decoder.pl
│ ├── qoi_encoder.pl
│ ├── qzst_decoder.pl
│ ├── qzst_encoder.pl
│ ├── recompress_images.pl
│ ├── remove_sensitive_exif_tags.pl
│ ├── resize_images.pl
│ ├── rgb_dump.pl
│ ├── sharp_2x_zoom.pl
│ ├── slideshow.pl
│ ├── vertical_scrambler.pl
│ ├── visualize_binary.pl
│ ├── webp2png.pl
│ ├── zuper_image_decoder.pl
│ └── zuper_image_encoder.pl
├── JAPH/
│ ├── alien_japh.pl
│ ├── alpha_ascii_japh.pl
│ ├── alpha_japh.pl
│ ├── alpha_japh_2.pl
│ ├── alpha_japh_3.pl
│ ├── arrow_japh.pl
│ ├── barewords_japh.pl
│ ├── cubic_japh.pl
│ ├── invisible_japh.pl
│ ├── japh_from_ambiguity.pl
│ ├── japh_from_auto-quoted_keywords.pl
│ ├── japh_from_escapes.pl
│ ├── japh_from_escapes_2.pl
│ ├── japh_from_eval_subst.pl
│ ├── japh_from_keywords.pl
│ ├── japh_from_pod.pl
│ ├── japh_from_poetry.pl
│ ├── japh_from_punctuation_chars.pl
│ ├── japh_from_subs.pl
│ ├── japh_from_the_deep.pl
│ ├── japh_variable.pl
│ ├── japh_variables.pl
│ ├── japh_variables_2.pl
│ ├── leet_japh.pl
│ ├── length_obfuscation.pl
│ ├── log_japh.pl
│ ├── log_japh_2.pl
│ ├── non-alphanumeric_japh.pl
│ ├── re_eval_japh.pl
│ ├── slash_r_japh.pl
│ ├── ternary_japh.pl
│ ├── up_and_down.pl
│ ├── vec_japh.pl
│ └── vec_japh_2.pl
├── LICENSE
├── Lingua/
│ ├── en_phoneme.pl
│ ├── lingua_ro_numbers.pl
│ ├── poetry_from_poetry.pl
│ ├── poetry_from_poetry_with_variations.pl
│ ├── random_poetry_generator.pl
│ └── rus_translit.pl
├── Math/
│ ├── 1_over_n_is_finite.pl
│ ├── 1_over_n_period_length.pl
│ ├── BPSW_primality_test.pl
│ ├── BPSW_primality_test_mpz.pl
│ ├── LUP_decomposition.pl
│ ├── MBE_factorization_method.pl
│ ├── PSW_primality_test.pl
│ ├── PSW_primality_test_mpz.pl
│ ├── RSA_PRNG.pl
│ ├── RSA_example.pl
│ ├── additive_binomial.pl
│ ├── additive_partitions.pl
│ ├── alexandrian_integers.pl
│ ├── almost_prime_divisors.pl
│ ├── almost_prime_divisors_recursive.pl
│ ├── almost_prime_numbers.pl
│ ├── almost_prime_numbers_in_range.pl
│ ├── almost_prime_numbers_in_range_mpz.pl
│ ├── almost_prime_numbers_in_range_v2.pl
│ ├── almost_primes_from_factor_list.pl
│ ├── almost_primes_in_range_from_factor_list.pl
│ ├── area_of_triangle.pl
│ ├── arithmetic_derivative.pl
│ ├── arithmetic_expressions.pl
│ ├── arithmetic_geometric_mean_complex.pl
│ ├── arithmetic_sum_closed_form.pl
│ ├── ascii_cuboid.pl
│ ├── ascii_julia_set.pl
│ ├── ascii_mandelbrot_set.pl
│ ├── batir_factorial_asymptotic_formula_mpfr.pl
│ ├── bell_numbers.pl
│ ├── bell_numbers_mpz.pl
│ ├── bernoulli_denominators.pl
│ ├── bernoulli_denominators_records.pl
│ ├── bernoulli_numbers.pl
│ ├── bernoulli_numbers_from_factorials.pl
│ ├── bernoulli_numbers_from_factorials_mpq.pl
│ ├── bernoulli_numbers_from_factorials_mpz.pl
│ ├── bernoulli_numbers_from_factorials_visual.pl
│ ├── bernoulli_numbers_from_primes.pl
│ ├── bernoulli_numbers_from_primes_gmpf.pl
│ ├── bernoulli_numbers_from_primes_mpfr.pl
│ ├── bernoulli_numbers_from_primes_ntheory.pl
│ ├── bernoulli_numbers_from_tangent_numbers.pl
│ ├── bernoulli_numbers_from_zeta.pl
│ ├── bernoulli_numbers_ramanujan_congruences.pl
│ ├── bernoulli_numbers_ramanujan_congruences_unreduced.pl
│ ├── bernoulli_numbers_recursive.pl
│ ├── bernoulli_numbers_recursive_2.pl
│ ├── bernoulli_numbers_seidel.pl
│ ├── bi-unitary_divisors.pl
│ ├── binary_gcd_algorithm.pl
│ ├── binary_gcd_algorithm_mpz.pl
│ ├── binary_multiplier.pl
│ ├── binary_prime_encoder.pl
│ ├── binary_prime_encoder_fast.pl
│ ├── binary_prime_sieve_mpz.pl
│ ├── binary_splitting_product.pl
│ ├── binomial_sum_with_imaginary_term.pl
│ ├── binomial_theorem.pl
│ ├── bitstring_prime_sieve_mpz.pl
│ ├── bitstring_prime_sieve_vec.pl
│ ├── both_truncatable_primes_in_base.pl
│ ├── brazilian_primes_constant.pl
│ ├── brown_numbers.pl
│ ├── carmichael_factorization_method.pl
│ ├── carmichael_factorization_method_generalized.pl
│ ├── carmichael_numbers_from_multiple.pl
│ ├── carmichael_numbers_from_multiple_mpz.pl
│ ├── carmichael_numbers_from_multiple_recursive_mpz.pl
│ ├── carmichael_numbers_generation_erdos_method.pl
│ ├── carmichael_numbers_generation_erdos_method_dynamic_programming.pl
│ ├── carmichael_numbers_in_range.pl
│ ├── carmichael_numbers_in_range_from_prime_factors.pl
│ ├── carmichael_numbers_in_range_mpz.pl
│ ├── carmichael_numbers_random.pl
│ ├── carmichael_strong_fermat_pseudoprimes_in_range.pl
│ ├── carmichael_strong_fermat_pseudoprimes_in_range_mpz.pl
│ ├── cartesian_product_iter.pl
│ ├── cartesian_product_rec.pl
│ ├── cauchy_numbers_of_first_type.pl
│ ├── chebyshev_factorization_method.pl
│ ├── chebyshev_factorization_method_mpz.pl
│ ├── chernick-carmichael_numbers.pl
│ ├── chernick-carmichael_numbers_below_limit.pl
│ ├── chernick-carmichael_polynomials.pl
│ ├── chernick-carmichael_with_n_factors_sieve.pl
│ ├── chinese_factorization_method.pl
│ ├── coin_change.pl
│ ├── collatz_function.pl
│ ├── complex_exponentiation_in_real_numbers.pl
│ ├── complex_logarithm_in_real_numbers.pl
│ ├── complex_modular_multiplicative_inverse.pl
│ ├── complex_zeta_in_real_numbers.pl
│ ├── congruence_of_powers_factorization_method.pl
│ ├── consecutive_partitions.pl
│ ├── continued_fraction_expansion_of_sqrt_of_n.pl
│ ├── continued_fraction_expansion_of_sqrt_of_n_mpz.pl
│ ├── continued_fraction_factorization_method.pl
│ ├── continued_fractions.pl
│ ├── continued_fractions_for_e.pl
│ ├── continued_fractions_for_nth_roots.pl
│ ├── continued_fractions_for_pi.pl
│ ├── continued_fractions_for_square_roots.pl
│ ├── continued_fractions_prime_constant.pl
│ ├── convergent_series.pl
│ ├── cosmic_calendar.pl
│ ├── count_of_brilliant_numbers.pl
│ ├── count_of_cube-full_numbers.pl
│ ├── count_of_integers_with_gpf_of_n_equals_p.pl
│ ├── count_of_integers_with_lpf_of_n_equals_p.pl
│ ├── count_of_inverse_tau_in_range.pl
│ ├── count_of_k-almost_primes.pl
│ ├── count_of_k-omega_primes.pl
│ ├── count_of_k-powerfree_numbers.pl
│ ├── count_of_k-powerful_numbers.pl
│ ├── count_of_k-powerful_numbers_in_range.pl
│ ├── count_of_perfect_powers.pl
│ ├── count_of_prime_power.pl
│ ├── count_of_prime_signature_numbers.pl
│ ├── count_of_rough_numbers.pl
│ ├── count_of_rough_numbers_recursive.pl
│ ├── count_of_smooth_numbers.pl
│ ├── count_of_smooth_numbers_memoized.pl
│ ├── count_of_smooth_numbers_mpz.pl
│ ├── count_of_smooth_numbers_mpz_2.pl
│ ├── count_of_smooth_numbers_with_k_factors.pl
│ ├── count_of_squarefree_k-almost_primes.pl
│ ├── count_of_squarefree_numbers.pl
│ ├── count_subtriangles.pl
│ ├── cube-full_numbers.pl
│ ├── cuboid.pl
│ ├── cyclotomic_factorization_method.pl
│ ├── cyclotomic_factorization_method_2.pl
│ ├── cyclotomic_polynomial.pl
│ ├── definite_integral_numerical_approximation.pl
│ ├── dickson_linear_forms_prime_sieve.pl
│ ├── dickson_linear_forms_prime_sieve_in_range.pl
│ ├── dickson_linear_forms_prime_sieve_in_range_2.pl
│ ├── difference_of_k_powers.pl
│ ├── difference_of_powers_factorization_method.pl
│ ├── difference_of_three_squares_solutions.pl
│ ├── difference_of_two_squares_solutions.pl
│ ├── digits_to_number_subquadratic_algorithm.pl
│ ├── digits_to_number_subquadratic_algorithm_mpz.pl
│ ├── dirichlet_hyperbola_method.pl
│ ├── discrete_logarithm_pollard_rho.pl
│ ├── discrete_logarithm_pollard_rho_mpz.pl
│ ├── discrete_root.pl
│ ├── divisors_descending_lazy.pl
│ ├── divisors_lazy.pl
│ ├── divisors_lazy_fast.pl
│ ├── divisors_less_than_k.pl
│ ├── divisors_of_factorial_below_limit.pl
│ ├── divisors_of_factorial_in_range_iterator.pl
│ ├── dixon_factorization_method.pl
│ ├── e_from_binomial.pl
│ ├── e_primorial.pl
│ ├── ecm_factorization_method.pl
│ ├── elementary_cellular_automaton_generalized.pl
│ ├── elliptic-curve_factorization_method.pl
│ ├── elliptic-curve_factorization_method_with_B2_stage.pl
│ ├── elliptic-curve_factorization_method_with_B2_stage_mpz.pl
│ ├── equally_spaced_squares_solutions.pl
│ ├── esthetic_numbers.pl
│ ├── ethiopian_multiplication.pl
│ ├── ethiopian_multiplication_binary.pl
│ ├── even_fermat_pseudoprimes_in_range.pl
│ ├── even_squarefree_fermat_pseudoprimes_in_range.pl
│ ├── exponential_divisors.pl
│ ├── factorial_difference_of_prime_squares.pl
│ ├── factorial_dsc_algorithm.pl
│ ├── factorial_expansion_of_reciprocals.pl
│ ├── factorial_from_primes.pl
│ ├── factorial_from_primes_simple.pl
│ ├── factorial_from_primorials.pl
│ ├── factorial_from_trinomial_coefficients.pl
│ ├── factorial_in_half_steps.pl
│ ├── factorions_in_base_n.pl
│ ├── factorization_with_difference_of_prime_factors.pl
│ ├── farey_rational_approximation.pl
│ ├── faulhaber_s_formula.pl
│ ├── fermat_factorization_method.pl
│ ├── fermat_factorization_method_2.pl
│ ├── fermat_frobenius_quadratic_primality_test.pl
│ ├── fermat_overpseudoprimes_generation.pl
│ ├── fermat_overpseudoprimes_in_range.pl
│ ├── fermat_pseudoprimes_from_multiple.pl
│ ├── fermat_pseudoprimes_from_multiple_mpz.pl
│ ├── fermat_pseudoprimes_generation.pl
│ ├── fermat_pseudoprimes_generation_2.pl
│ ├── fermat_pseudoprimes_generation_3.pl
│ ├── fermat_pseudoprimes_in_range.pl
│ ├── fermat_pseudoprimes_in_range_mpz.pl
│ ├── fermat_superpseudoprimes_generation.pl
│ ├── fibonacci_closed_form.pl
│ ├── fibonacci_closed_form_2.pl
│ ├── fibonacci_encoding.pl
│ ├── fibonacci_factorization_method.pl
│ ├── fibonacci_k-th_order.pl
│ ├── fibonacci_k-th_order_efficient_algorithm.pl
│ ├── fibonacci_k-th_order_fast.pl
│ ├── fibonacci_k-th_order_odd_primes_indices.pl
│ ├── fibonacci_number_fast.pl
│ ├── fibonacci_polynomials_closed_form.pl
│ ├── fibonacci_pseudoprimes_generation.pl
│ ├── find_least_common_denominator.pl
│ ├── floor_and_ceil_functions_fourier_series.pl
│ ├── flt_factorization_method.pl
│ ├── fraction_approximation.pl
│ ├── fraction_to_decimal_expansion.pl
│ ├── fractional_pi.pl
│ ├── frobenius_pseudoprimes_generation.pl
│ ├── fubini_numbers.pl
│ ├── fubini_numbers_2.pl
│ ├── fubini_numbers_recursive.pl
│ ├── function_graph.pl
│ ├── function_inverse_binary_search.pl
│ ├── gamma_function.pl
│ ├── gaussian_divisors.pl
│ ├── gaussian_factors.pl
│ ├── gaussian_integers_sum.pl
│ ├── general_binary_multiplier.pl
│ ├── goldbach_conjecture_2n_prime.pl
│ ├── goldbach_conjecture_increasing_primes.pl
│ ├── goldbach_conjecture_possibilities.pl
│ ├── goldbach_conjecture_random_primes.pl
│ ├── golomb_s_sequence.pl
│ ├── greatest_common_unitary_divisor.pl
│ ├── hamming_numbers.pl
│ ├── harmonic_numbers.pl
│ ├── harmonic_numbers_from_digamma.pl
│ ├── harmonic_numbers_from_powers.pl
│ ├── harmonic_numbers_from_powers_mpz.pl
│ ├── harmonic_prime_powers.pl
│ ├── hybrid_prime_factorization.pl
│ ├── infinitary_divisors.pl
│ ├── inverse_of_bernoulli_numbers.pl
│ ├── inverse_of_euler_totient.pl
│ ├── inverse_of_factorial.pl
│ ├── inverse_of_factorial_stirling.pl
│ ├── inverse_of_fibonacci.pl
│ ├── inverse_of_multiplicative_functions.pl
│ ├── inverse_of_p_adic_valuation.pl
│ ├── inverse_of_sigma_function.pl
│ ├── inverse_of_sigma_function_fast.pl
│ ├── inverse_of_sigma_function_generalized.pl
│ ├── inverse_of_usigma_function.pl
│ ├── inverse_tau_in_range.pl
│ ├── invert_transform_of_factorials.pl
│ ├── is_absolute_euler_pseudoprime.pl
│ ├── is_almost_prime.pl
│ ├── is_bfsw_pseudoprime.pl
│ ├── is_chernick_carmichael_number.pl
│ ├── is_even_perfect.pl
│ ├── is_even_perfect_2.pl
│ ├── is_even_perfect_3.pl
│ ├── is_extra_bfsw_pseudoprime.pl
│ ├── is_omega_prime.pl
│ ├── is_perfect_power.pl
│ ├── is_smooth_over_product.pl
│ ├── is_squarefree_over_product.pl
│ ├── is_sum_of_two_cubes.pl
│ ├── is_sum_of_two_squares.pl
│ ├── iterative_difference_of_central_divisors_to_reach_zero.pl
│ ├── k-imperfect_numbers.pl
│ ├── k-odd-powerful_numbers.pl
│ ├── k-powerful_numbers.pl
│ ├── k-powerful_numbers_in_range.pl
│ ├── karatsuba_multiplication.pl
│ ├── kempner_binomial_numbers.pl
│ ├── klein_J_invariant_and_modular_lambda.pl
│ ├── lambert_W_function.pl
│ ├── lambert_W_function_complex.pl
│ ├── lanczos_approximation.pl
│ ├── least_k_such_that_k_times_k-th_prime_is_greater_than_10_to_the_n.pl
│ ├── least_nonresidue.pl
│ ├── legendary_question_six.pl
│ ├── length_of_shortest_addition_chain.pl
│ ├── lerch_zeta_function.pl
│ ├── logarithmic_integral_asymptotic_formula.pl
│ ├── logarithmic_root.pl
│ ├── logarithmic_root_complex.pl
│ ├── logarithmic_root_in_two_variables.pl
│ ├── logarithmic_root_mpfr.pl
│ ├── long_division.pl
│ ├── long_multiplication.pl
│ ├── lucas-carmichael_numbers_from_multiple.pl
│ ├── lucas-carmichael_numbers_from_multiple_mpz.pl
│ ├── lucas-carmichael_numbers_in_range.pl
│ ├── lucas-carmichael_numbers_in_range_from_prime_factors.pl
│ ├── lucas-carmichael_numbers_in_range_mpz.pl
│ ├── lucas-miller_factorization_method.pl
│ ├── lucas-pocklington_primality_proving.pl
│ ├── lucas-pratt_primality_proving.pl
│ ├── lucas-pratt_prime_records.pl
│ ├── lucas_factorization_method.pl
│ ├── lucas_factorization_method_generalized.pl
│ ├── lucas_pseudoprimes_generation.pl
│ ├── lucas_pseudoprimes_generation_erdos_method.pl
│ ├── lucas_sequences_U_V.pl
│ ├── lucas_sequences_U_V_mpz.pl
│ ├── lucas_theorem.pl
│ ├── magic_3-gon_ring.pl
│ ├── magic_5-gon_ring.pl
│ ├── map_num.pl
│ ├── matrix_determinant_bareiss.pl
│ ├── matrix_path_2-ways_best.pl
│ ├── matrix_path_2-ways_greedy.pl
│ ├── matrix_path_3-ways_best.pl
│ ├── matrix_path_3-ways_diagonal_best.pl
│ ├── matrix_path_3-ways_greedy.pl
│ ├── matrix_path_4-ways_best.pl
│ ├── matrix_path_4-ways_best_2.pl
│ ├── matrix_path_4-ways_best_3.pl
│ ├── matrix_path_4-ways_greedy.pl
│ ├── maximum_product_of_parts_bisection.pl
│ ├── maximum_square_remainder.pl
│ ├── meissel_lehmer_prime_count.pl
│ ├── mertens_function.pl
│ ├── mertens_function_fast.pl
│ ├── miller-rabin_deterministic_primality_test.pl
│ ├── miller-rabin_deterministic_primality_test_mpz.pl
│ ├── miller-rabin_factorization_method.pl
│ ├── modular_bell_numbers.pl
│ ├── modular_bell_numbers_mpz.pl
│ ├── modular_binomial.pl
│ ├── modular_binomial_fast.pl
│ ├── modular_binomial_faster.pl
│ ├── modular_binomial_faster_mpz.pl
│ ├── modular_binomial_faster_mpz_2.pl
│ ├── modular_binomial_ntheory.pl
│ ├── modular_binomial_small_k.pl
│ ├── modular_binomial_small_k_faster.pl
│ ├── modular_cyclotomic_polynomial.pl
│ ├── modular_factorial.pl
│ ├── modular_factorial_crt.pl
│ ├── modular_factorial_crt_mpz.pl
│ ├── modular_fibonacci.pl
│ ├── modular_fibonacci_anynum.pl
│ ├── modular_fibonacci_cassini.pl
│ ├── modular_fibonacci_cassini_fast.pl
│ ├── modular_fibonacci_fast_mpz.pl
│ ├── modular_fibonacci_mpz.pl
│ ├── modular_fibonacci_polynomial.pl
│ ├── modular_fibonacci_polynomial_2.pl
│ ├── modular_hyperoperation.pl
│ ├── modular_inverse.pl
│ ├── modular_k-th_root_all_solutions.pl
│ ├── modular_k-th_root_all_solutions_fast.pl
│ ├── modular_k-th_root_all_solutions_fast_mpz.pl
│ ├── modular_k-th_root_all_solutions_mpz.pl
│ ├── modular_lucas_numbers.pl
│ ├── modular_lucas_sequence_V.pl
│ ├── modular_lucas_sequences_U_V.pl
│ ├── modular_pseudo_square_root.pl
│ ├── modular_pseudo_square_root_2.pl
│ ├── modular_sigma_of_unitary_divisors_of_factorial.pl
│ ├── modular_square_root.pl
│ ├── modular_square_root_2.pl
│ ├── modular_square_root_3.pl
│ ├── modular_square_root_all_solutions.pl
│ ├── modular_square_root_all_solutions_cipolla.pl
│ ├── multi_sqrt_nums.pl
│ ├── multinomial_coefficient.pl
│ ├── multinomial_coefficient_from_binomial.pl
│ ├── multiplicative_partitions.pl
│ ├── multisets.pl
│ ├── multivariate_gamma_function.pl
│ ├── mysterious_sum-pentagonal_numbers.pl
│ ├── mysterious_sum-pentagonal_numbers_2.pl
│ ├── n_dimensional_circles.pl
│ ├── near-power_factorization_method.pl
│ ├── newton_s_method.pl
│ ├── newton_s_method_recursive.pl
│ ├── next_palindrome.pl
│ ├── next_palindrome_from_non-palindrome.pl
│ ├── next_palindrome_in_base.pl
│ ├── next_power_of_two.pl
│ ├── nth_composite.pl
│ ├── nth_digit_of_fraction.pl
│ ├── nth_prime_approx.pl
│ ├── nth_root_good_rational_approximations.pl
│ ├── nth_root_recurrence_constant.pl
│ ├── nth_smooth_number.pl
│ ├── number2expression.pl
│ ├── number_of_conditional_GCDs.pl
│ ├── number_of_connected_permutations.pl
│ ├── number_of_partitions_into_2_distinct_positive_cubes.pl
│ ├── number_of_partitions_into_2_distinct_positive_squares.pl
│ ├── number_of_partitions_into_2_nonnegative_cubes.pl
│ ├── number_of_partitions_into_2_positive_squares.pl
│ ├── number_of_representations_as_sum_of_3_triangles.pl
│ ├── number_of_representations_as_sum_of_four_squares.pl
│ ├── number_of_representations_as_sum_of_two_squares.pl
│ ├── number_to_digits_subquadratic_algorithm.pl
│ ├── number_to_digits_subquadratic_algorithm_mpz.pl
│ ├── numbers_with_pow_2_divisors.pl
│ ├── omega_prime_divisors.pl
│ ├── omega_prime_numbers_in_range.pl
│ ├── omega_prime_numbers_in_range_mpz.pl
│ ├── omega_prime_numbers_in_range_simple.pl
│ ├── order_factorization_method.pl
│ ├── palindrome_iteration.pl
│ ├── partial_sums_of_dedekind_psi_function.pl
│ ├── partial_sums_of_euler_totient_function.pl
│ ├── partial_sums_of_euler_totient_function_fast.pl
│ ├── partial_sums_of_euler_totient_function_fast_2.pl
│ ├── partial_sums_of_euler_totient_function_times_k.pl
│ ├── partial_sums_of_euler_totient_function_times_k_to_the_m.pl
│ ├── partial_sums_of_exponential_prime_omega_functions.pl
│ ├── partial_sums_of_gcd-sum_function.pl
│ ├── partial_sums_of_gcd-sum_function_fast.pl
│ ├── partial_sums_of_gcd-sum_function_faster.pl
│ ├── partial_sums_of_generalized_gcd-sum_function.pl
│ ├── partial_sums_of_gpf.pl
│ ├── partial_sums_of_inverse_moebius_transform_of_dedekind_function.pl
│ ├── partial_sums_of_jordan_totient_function.pl
│ ├── partial_sums_of_jordan_totient_function_fast.pl
│ ├── partial_sums_of_jordan_totient_function_times_k_to_the_m.pl
│ ├── partial_sums_of_lcm_count_function.pl
│ ├── partial_sums_of_liouville_function.pl
│ ├── partial_sums_of_lpf.pl
│ ├── partial_sums_of_n_over_k-almost_prime_divisors.pl
│ ├── partial_sums_of_powerfree_numbers.pl
│ ├── partial_sums_of_powerfree_part.pl
│ ├── partial_sums_of_prime_bigomega_function.pl
│ ├── partial_sums_of_prime_omega_function.pl
│ ├── partial_sums_of_sigma0_function.pl
│ ├── partial_sums_of_sigma_function.pl
│ ├── partial_sums_of_sigma_function_times_k.pl
│ ├── partial_sums_of_sigma_function_times_k_to_the_m.pl
│ ├── partitions_count.pl
│ ├── partitions_count_abs.pl
│ ├── partitions_count_simple.pl
│ ├── pascal-fibonacci_triangle.pl
│ ├── pascal_s_triangle_multiples.pl
│ ├── pattern_mixing.pl
│ ├── pell_cfrac_factorization.pl
│ ├── pell_factorization.pl
│ ├── pell_factorization_anynum.pl
│ ├── perfect_numbers.pl
│ ├── period_of_continued_fraction_for_square_roots.pl
│ ├── period_of_continued_fraction_for_square_roots_mpz.pl
│ ├── period_of_continued_fraction_for_square_roots_ntheory.pl
│ ├── phi-finder_factorization_method.pl
│ ├── pi_from_infinity.pl
│ ├── pisano_periods.pl
│ ├── pisano_periods_efficient_algorithm.pl
│ ├── pocklington-pratt_primality_proving.pl
│ ├── pollard-strassen_factorization_method.pl
│ ├── pollard_p-1_factorization.pl
│ ├── pollard_rho_exp_factorization.pl
│ ├── pollard_rho_factorization.pl
│ ├── polygonal_numbers.pl
│ ├── polygonal_representations.pl
│ ├── polynomial_interpolation.pl
│ ├── power_divisors.pl
│ ├── power_of_factorial_ramanujan.pl
│ ├── power_unitary_divisors.pl
│ ├── powerfree_divisors.pl
│ ├── powers_of_primes_in_factorial.pl
│ ├── powers_of_primes_modulus_in_factorial.pl
│ ├── prime_41.pl
│ ├── prime_abundant_sequences.pl
│ ├── prime_count_smooth_sum.pl
│ ├── prime_counting_from_almost_primes.pl
│ ├── prime_counting_from_squarefree_almost_primes.pl
│ ├── prime_counting_liouville_formula.pl
│ ├── prime_counting_mertens_formula.pl
│ ├── prime_factorization_concept.pl
│ ├── prime_factors_of_binomial_coefficients.pl
│ ├── prime_factors_of_binomial_product.pl
│ ├── prime_factors_of_factorial.pl
│ ├── prime_factors_of_superfactorial_and_hyperfactorial.pl
│ ├── prime_formulas.pl
│ ├── prime_functions_in_terms_of_zeros_of_zeta.pl
│ ├── prime_numbers_generator.pl
│ ├── prime_omega_function_generalized.pl
│ ├── prime_quadratic_polynomial_analyzer.pl
│ ├── prime_quadratic_polynomials.pl
│ ├── prime_signature_numbers_in_range.pl
│ ├── prime_summation.pl
│ ├── prime_zeta.pl
│ ├── primes_diff.pl
│ ├── primes_sum_of_pair_product.pl
│ ├── primitive_sum_of_two_squares.pl
│ ├── primorial_deflation.pl
│ ├── pseudo_square_root.pl
│ ├── pythagorean_triples.pl
│ ├── quadratic-integer_factorization_method.pl
│ ├── quadratic-integer_factorization_method_mpz.pl
│ ├── quadratic_frobenius_primality_test.pl
│ ├── quadratic_frobenius_pseudoprimes_generation.pl
│ ├── quadratic_polynomial_in_terms_of_its_zeros.pl
│ ├── ramanujan_sum.pl
│ ├── ramanujan_sum_fast.pl
│ ├── random_carmichael_fibonacci_pseudoprimes.pl
│ ├── random_integer_factorization.pl
│ ├── random_miller-rabin_pseudoprimes.pl
│ ├── range_map.pl
│ ├── rational_approximations.pl
│ ├── rational_continued_fractions.pl
│ ├── rational_prime_product.pl
│ ├── rational_summation_of_fractions.pl
│ ├── reciprocal_cycle_length.pl
│ ├── rectangle_sides_from_area_and_diagonal.pl
│ ├── rectangle_sides_from_diagonal_angles.pl
│ ├── rectangle_sides_from_one_diagonal_angle.pl
│ ├── recursive_matrix_multiplication.pl
│ ├── rest_calc.pl
│ ├── reversed_number_triangle.pl
│ ├── reversed_number_triangles.pl
│ ├── riemann_prime-counting_function.pl
│ ├── riemann_s_J_function.pl
│ ├── roots_on_the_rise.pl
│ ├── secant_numbers.pl
│ ├── semiprime_equationization.pl
│ ├── semiprime_equationization_uncached.pl
│ ├── sequence_analyzer.pl
│ ├── sequence_closed_form.pl
│ ├── sequence_polynomial_closed_form.pl
│ ├── sieve_of_eratosthenes.pl
│ ├── sigma0_of_factorial.pl
│ ├── sigma_function.pl
│ ├── sigma_of_factorial.pl
│ ├── sigma_of_product_of_binomials.pl
│ ├── sigma_p_adic.pl
│ ├── siqs_factorization.pl
│ ├── smallest_carmichael_divisible_by_n.pl
│ ├── smallest_k-gonal_inverse.pl
│ ├── smallest_k-gonal_inverse_brute_force.pl
│ ├── smallest_lucas-carmichael_divisible_by_n.pl
│ ├── smallest_number_with_at_least_n_divisors.pl
│ ├── smallest_number_with_n_divisors.pl
│ ├── smarandache_function.pl
│ ├── smooth_numbers_generalized.pl
│ ├── solutions_to_x_squared_equals_-1_mod_n.pl
│ ├── solutions_to_x_squared_equals_1_mod_n.pl
│ ├── solutions_to_x_squared_equals_a_mod_n.pl
│ ├── solve_congruence_equation_example.pl
│ ├── solve_cubic_equation.pl
│ ├── solve_cubic_equation_real.pl
│ ├── solve_modular_cubic_equation.pl
│ ├── solve_modular_quadratic_equation.pl
│ ├── solve_pell_equation.pl
│ ├── solve_pell_equation_fast.pl
│ ├── solve_pell_equation_generalized.pl
│ ├── solve_pell_equation_simple.pl
│ ├── solve_quadratic_diophantine_reciprocals.pl
│ ├── solve_reciprocal_pythagorean_equation.pl
│ ├── solve_sequence.pl
│ ├── sophie_germain_factorization_method.pl
│ ├── sorting_algorithms.pl
│ ├── sphere_volume.pl
│ ├── sqrt_mod_p_tonelli-shanks_mpz.pl
│ ├── square_divisors.pl
│ ├── square_product_subsets.pl
│ ├── square_root_convergents.pl
│ ├── square_root_method.pl
│ ├── square_root_modulo_n_tonelli-shanks.pl
│ ├── squarefree_almost_prime_divisors.pl
│ ├── squarefree_almost_primes_from_factor_list.pl
│ ├── squarefree_almost_primes_in_range.pl
│ ├── squarefree_almost_primes_in_range_from_factor_list.pl
│ ├── squarefree_almost_primes_in_range_mpz.pl
│ ├── squarefree_divisors.pl
│ ├── squarefree_fermat_overpseudoprimes_in_range.pl
│ ├── squarefree_fermat_pseudoprimes_in_range.pl
│ ├── squarefree_fermat_pseudoprimes_in_range_mpz.pl
│ ├── squarefree_lucas_U_pseudoprimes_in_range.pl
│ ├── squarefree_strong_fermat_pseudoprimes_in_range.pl
│ ├── squarefree_strong_fermat_pseudoprimes_in_range_mpz.pl
│ ├── squarefree_strong_fermat_pseudoprimes_to_multiple_bases_in_range.pl
│ ├── squarefree_strong_fermat_pseudoprimes_to_multiple_bases_in_range_mpz.pl
│ ├── stern_brocot_encoding.pl
│ ├── stern_brocot_sequence.pl
│ ├── strong_fermat_pseudoprimes_in_range.pl
│ ├── strong_fermat_pseudoprimes_in_range_mpz.pl
│ ├── sub-unit_squares.pl
│ ├── sum_factorial.pl
│ ├── sum_of_an_even_number_of_positive_squares.pl
│ ├── sum_of_digits.pl
│ ├── sum_of_digits_subquadratic_algorithm.pl
│ ├── sum_of_digits_subquadratic_algorithm_mpz.pl
│ ├── sum_of_k-powerful_numbers_in_range.pl
│ ├── sum_of_natural_powers_in_constant_base.pl
│ ├── sum_of_perfect_powers.pl
│ ├── sum_of_prime-power_exponents_of_factorial.pl
│ ├── sum_of_prime-power_exponents_of_product_of_binomials.pl
│ ├── sum_of_prime_powers.pl
│ ├── sum_of_primes_generalized.pl
│ ├── sum_of_sigma.pl
│ ├── sum_of_sigma_2.pl
│ ├── sum_of_the_number_of_divisors.pl
│ ├── sum_of_the_number_of_divisors_of_gcd_x_y.pl
│ ├── sum_of_the_number_of_unitary_divisors.pl
│ ├── sum_of_the_sum_of_divisors.pl
│ ├── sum_of_three_cubes_problem.pl
│ ├── sum_of_triangular_numbers_solutions.pl
│ ├── sum_of_two_primes.pl
│ ├── sum_of_two_squares_all_solutions.pl
│ ├── sum_of_two_squares_all_solutions_2.pl
│ ├── sum_of_two_squares_all_solutions_tonelli-shanks.pl
│ ├── sum_of_two_squares_multiple_solutions.pl
│ ├── sum_of_two_squares_solution.pl
│ ├── sum_remainders.pl
│ ├── super_pandigital_numbers.pl
│ ├── tangent_numbers.pl
│ ├── trial_division_fast.pl
│ ├── triangle_hyperoperation.pl
│ ├── triangle_interior_angles.pl
│ ├── tribonacci_primality_test.pl
│ ├── trip2mars.pl
│ ├── unique_permutations.pl
│ ├── unitary_divisors.pl
│ ├── unitary_divisors_fast.pl
│ ├── unitary_squarefree_divisors.pl
│ ├── wilson_prime_formula.pl
│ ├── yahtzee.pl
│ ├── zequals.pl
│ ├── zeta_2n.pl
│ ├── zeta_for_primes.pl
│ ├── zeta_function.pl
│ └── zeta_prime_count_approx.pl
├── Media/
│ └── wimp-viewer
├── Microphone/
│ ├── Alsa/
│ │ └── raw_from_microphone.pl
│ └── Julius/
│ ├── julius_voice_control_concept.pl
│ └── voice_control.pl
├── Monitoring/
│ └── file-monitor
├── Other/
│ ├── concatenation_weirdness.pl
│ ├── lexical_subs_recursion_bug.pl
│ ├── tail_recursion.pl
│ └── yafu_factorization.pl
├── README.md
├── Regex/
│ ├── positive-negative_matching.pl
│ ├── prime_regexp.pl
│ ├── regex_optimizer_in_source.pl
│ ├── regex_pair_factors.pl
│ └── regexp_to_strings.pl
├── Search/
│ ├── binary_search.pl
│ ├── binary_search_ge.pl
│ └── binary_search_le.pl
├── Shell/
│ └── execute_perl_scripts.pl
├── Simulation/
│ └── 100_prisoners_riddle.pl
├── Socket/
│ └── chat_server.pl
├── Sort/
│ ├── binsertion_sorting_algorithm.pl
│ └── dream_sort.pl
├── Subtitle/
│ ├── srt-delay
│ ├── srt_assembler.pl
│ └── srt_fix.pl
├── Text/
│ ├── abs_string.pl
│ ├── all_substrings.pl
│ ├── change-encoding.pl
│ ├── group_alike_words.pl
│ ├── jaro-winkler_distance.pl
│ ├── levenshtein_distance_iter.pl
│ ├── levenshtein_distance_rec.pl
│ ├── markov_chain_text_generator.pl
│ ├── orthogonal_text_scrambling.pl
│ ├── orthogonal_text_scrambling_double.pl
│ ├── repeated_substrings.pl
│ ├── search_by_prefix.pl
│ ├── sim_end_words.pl
│ ├── smartWordWrap.pl
│ ├── smartWordWrap_lazy.pl
│ ├── smartWordWrap_simple.pl
│ ├── unique_prefixes.pl
│ ├── word_roots.pl
│ └── word_unscrambler.pl
├── Time/
│ ├── calendar.pl
│ └── contdown.pl
├── Video/
│ ├── sponsor-free.pl
│ ├── video_concat_ffmpeg.pl
│ └── video_split_ffmpeg.pl
├── Visualisators/
│ ├── binview.pl
│ ├── disk-stats.pl
│ ├── dnscrypt_stats.pl
│ ├── greycmd.pl
│ ├── human-finder-visual.pl
│ ├── lz_visual.pl
│ ├── matrix_path_2-ways_best.pl
│ ├── matrix_path_3-ways_best.pl
│ ├── matrix_path_3-ways_greedy.pl
│ ├── pview
│ ├── random_finder_visual.pl
│ ├── triangle_sub-string_finder.pl
│ ├── visual_lz77_compression.pl
│ └── visual_sudoku_dice_solver.pl
└── update_readme.pl
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/blib/
/.build/
_build/
cover_db/
inc/
Build
!Build/
Build.bat
.last_cover_stats
/Makefile
/Makefile.old
/MANIFEST.bak
/META.yml
/META.json
/MYMETA.*
nytprof.out
/pm_to_blib
*.o
*.bs
Math/convergent_series.db
Research/
================================================
FILE: Analyzers/char_counter.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Count and list the unique characters within a file.
use strict;
use warnings;
use open IO => ':utf8', ':std';
my $file = shift @ARGV;
die "usage: $0 file\n" unless -f $file;
my %hash;
open my $fh, '<', $file;
while (defined(my $l = getc $fh)) {
next if exists $hash{$l};
$hash{$l} = ();
}
close $fh;
{
local $, = ' ';
print '-' x 80 . "\n";
print my (@list) = (sort { lc $a cmp lc $b } keys %hash);
print "\n" . '-' x 80 . "\n";
print unpack('C*', join('', @list));
print "\n" . '-' x 80 . "\n";
}
printf "\n** Unique characters used: %d\n\n", scalar keys %hash;
================================================
FILE: Analyzers/chr_freq.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 30 March 2012
# https://github.com/trizen
# Count Character Frequency in a file
use 5.010;
use strict;
use warnings;
use open IO => ':utf8', ':std';
my %table;
my %memoize;
my %white_spaces = (
ord("\r") => q{\r},
ord("\n") => q{\n},
ord("\f") => q{\f},
ord("\t") => q{\t},
ord(" ") => q{' '},
);
my $file = shift // $0;
open my $fh, '<', $file or die "Unable to open $file: $!";
while (defined(my $char = getc $fh)) {
++$table{
$memoize{$char} // do {
$memoize{$char} = ord $char;
}
};
}
close $fh;
$= = 80;
format STDOUT_TOP =
CHR ORD USED
-----------------------------------
.
my $key;
format STDOUT =
@>> @>>>>>> @>>>>>>
$white_spaces{$key} // chr $key, $key, $table{$key}
.
foreach $key (sort { $table{$b} <=> $table{$a} } keys %table) {
write;
}
say "\nUnique characters used: ", scalar keys %table;
================================================
FILE: Analyzers/dieharder.pl
================================================
#!/usr/bin/perl
#
## Test Perl's pseudorandom number generator with `dieharder`.
#
# usage:
# perl dieharder.pl > rand.txt && dieharder -g 202 -f rand.txt -a
use 5.014;
use strict;
use warnings;
my $seed = srand();
my $count = 1e6;
my $bits = 32;
print <<"EOT";
#==================================================================
# generator lcg seed = $seed
#==================================================================
type: d
count: $count
numbit: $bits
EOT
my $max = 2**$bits;
for (1 .. $count) {
say int(rand($max));
}
================================================
FILE: Analyzers/first_letter_top.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 25 June 2016
# Website: https://github.com/trizen
# Make a top with the first letters of each word in a given text.
# usage: cat file.txt | perl first_letter_top.pl
use 5.014;
use strict;
use warnings;
use List::Util qw(sum);
use open IO => ':utf8', ':std';
my %table;
foreach my $word (split(' ', do { local $/; <> })) {
if ($word =~ /^[^\pL]*(\pL)/) {
$table{lc($1)}++;
}
}
my $max = sum(values %table);
foreach my $key (sort { $table{$b} <=> $table{$a} } keys %table) {
printf("%s -> %3d (%5.2f%%)\n", $key, $table{$key}, $table{$key} / $max * 100);
}
================================================
FILE: Analyzers/kcal/kcal.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 13 February 2015
# Website: https://github.com/trizen
# Analyze a CSV list of products based on their values.
# (the energy expressed in kcal/100g divided by the price/100g)
use 5.010;
use strict;
use autodie;
use warnings;
use Text::CSV;
my $input_file = shift() // 'products.csv';
sub process_products_file {
my ($file) = @_;
my $csv = Text::CSV->new(
{
allow_whitespace => 1,
sep_char => ',',
}
)
or die "Cannot use CSV: " . Text::CSV->error_diag();
open my $fh, '<:encoding(UTF-8)', $file;
my @columns = map { lc(s/\W.*//rs) } @{$csv->getline($fh)};
$csv->column_names(@columns);
my @products;
while (my $row = $csv->getline_hr($fh)) {
push @products, {%{$row}, value => $row->{kcal} / $row->{price}};
}
return @products;
}
my @products = process_products_file($input_file);
my @sorted_products = sort { $b->{value} <=> $a->{value} } @products;
foreach my $product (@sorted_products) {
printf("%-35s%-10g%-10g(%g)\n", $product->{name}, $product->{kcal}, $product->{price}, $product->{value});
}
================================================
FILE: Analyzers/kcal/products.csv
================================================
name, kcal/100g, price/100g
Milk (1.5% fat),44,0.3
Dark chocolate (50% cacao),519,2.7
Mustard,178,0.93
Mountain dew,52,0.54
Sour cream (12% fat),131,0.7
Sour cream (20% fat),207,0.9
Pearl barley,352,0.3
Corn flour,350,0.2
Pufuleti,427,1.2
Beer,40,0.37
Chocolate (30% cacao),521,2.45
Yogurt (2.5% fat),51,0.38
Fish eggs,553,1.53
Strong beer,53,0.4
Eggs,130,0.86
Wheat flakes,304,0.4
Pork meat,541,2.4
Ice cream,226,1.6
================================================
FILE: Analyzers/kernel_config_diff.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 16 March 2013
# https://github.com/trizen
# List activated options from config_2, which are
# not activated in config_1, or have different values.
# Will print them in CSV format.
use 5.010;
use strict;
use autodie;
use warnings;
use Text::CSV qw();
$#ARGV == 1 or die <<"USAGE";
usage: $0 [config_1] [config_2]
USAGE
my ($config_1, $config_2) = @ARGV;
sub parse_option {
my ($line) = @_;
if ($line =~ /^(CONFIG_\w+)=(.*)$/) {
return $1, $2;
}
elsif ($line =~ /^# (CONFIG_\w+) is not set$/) {
return $1, undef;
}
elsif ($line =~ /^\W*CONFIG_\w/) {
die "ERROR: Can't parse line: $line\n";
}
return;
}
my %table;
{
open my $fh, '<', $config_1;
while (<$fh>) {
my ($name, $value) = parse_option($_);
$name // next;
$table{$name} = $value;
}
}
{
my $csv = Text::CSV->new({binary => 1, eol => "\n"})
or die "Cannot use CSV: " . Text::CSV->error_diag();
$csv->print(\*STDOUT, ["OPTION NAME", $config_1, $config_2]);
open my $fh, '<', $config_2;
while (<$fh>) {
my ($name, $value) = parse_option($_);
$name // next;
if (defined $value) {
if (not defined $table{$name}) {
$csv->print(\*STDOUT, [$name, (exists $table{$name} ? "is not set" : "-"), $value]);
}
else {
if ($table{$name} ne $value) {
$csv->print(\*STDOUT, [$name, $table{$name}, $value]);
}
}
}
}
}
================================================
FILE: Analyzers/perl_code_analyzer.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 04 January 2015
# Website: https://github.com/trizen
#
## Analyze your Perl code and see whether you are or not a true Perl hacker!
#
# More info about this script:
# https://trizenx.blogspot.com/2015/01/perl-code-analyzer.html
use utf8;
use 5.010;
use strict;
use warnings;
use IPC::Open2 qw(open2);
use Encode qw(encode_utf8 decode_utf8);
use Getopt::Long qw(GetOptions);
use Algorithm::Diff qw(LCS_length);
use Perl::Tokenizer qw(perl_tokens);
my $strict_level = 1;
my %ignored_types;
sub help {
my ($code) = @_;
print <<"HELP";
usage: $0 [options] [file] [...]
options:
--strict [level] : sets the strictness level (default: $strict_level)
Valid strict levels:
>= 1 : ignores strings, PODs, comments, spaces and semicolons
>= 2 : ignores round parentheses
>= 3 : ignores here-documents, (q|qq|qw|qx) quoted strings
>= 4 : ignores hex and binary literal numbers
If level=0, any stricture will be disabled.
HELP
exit($code // 0);
}
GetOptions('strict=i' => \$strict_level,
'help|h' => sub { help(0) },)
or die("Error in command line arguments\n");
@ARGV || help(2);
if ($strict_level >= 1) {
@ignored_types{
qw(
pod
data
comment
vertical_space
horizontal_space
other_space
semicolon
double_quoted_string
single_quoted_string
)
} = ();
}
if ($strict_level >= 2) {
@ignored_types{
qw(
parenthesis_open
parenthesis_close
)
} = ();
}
if ($strict_level >= 3) {
@ignored_types{
qw(
heredoc
heredoc_beg
q_string
qq_string
qw_string
qx_string
)
} = ();
}
if ($strict_level >= 4) {
@ignored_types{
qw(
hex_number
binary_number
)
} = ();
}
sub deparse {
my ($code) = @_;
local (*CHLD_IN, *CHLD_OUT);
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, $^X, '-MO=Deparse', '-T');
print CHLD_IN encode_utf8($code);
close(CHLD_IN);
my $deparsed = do {
local $/;
decode_utf8(<CHLD_OUT>);
};
waitpid($pid, 0);
my $child_exit_status = $? >> 8;
if ($child_exit_status != 0) {
die "B::Deparse failed with code: $child_exit_status\n";
}
return $deparsed;
}
sub get_tokens {
my ($code) = @_;
my @tokens;
perl_tokens {
my ($token) = @_;
if (not exists $ignored_types{$token}) {
push @tokens, $token;
}
}
$code;
return @tokens;
}
foreach my $script (@ARGV) {
print STDERR "=> Analyzing: $script\n";
my $code = do {
open my $fh, '<:utf8', $script;
local $/;
<$fh>;
};
my $d_code = eval { deparse($code) };
$@ && do { warn $@; next };
my @types = get_tokens($code);
my @d_types = get_tokens($d_code);
if (@types == 0 or @d_types == 0) {
warn "This script seems to be empty! Skipping...\n";
next;
}
my $len = LCS_length(\@types, \@d_types) - abs(@types - @d_types);
my $score = (100 - ($len / @types * 100));
if ($score >= 60) {
printf("WOW!!! We have here a score of %.2f! This is obfuscation, isn't it?\n", $score);
}
elsif ($score >= 40) {
printf("Outstanding! This code seems to be written by a true legend! Score: %.2f\n", $score);
}
elsif ($score >= 20) {
printf("Amazing! This code is very unique! Score: %.2f\n", $score);
}
elsif ($score >= 15) {
printf("Excellent! This code is written by a true Perl hacker. Score: %.2f\n", $score);
}
elsif ($score >= 10) {
printf("Awesome! This code is written by a Perl expert. Score: %.2f\n", $score);
}
elsif ($score >= 5) {
printf("Just OK! We have a score of %.2f! This is production code, isn't it?\n", $score);
}
else {
printf("What is this? I guess it is some baby Perl code, isn't it? Score: %.2f\n", $score);
}
}
================================================
FILE: Analyzers/perl_code_spellcheck.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 29 January 2017
# https://github.com/trizen
# Checks English words for spelling errors in Perl code.
# It tries to minimize false positives as much as possible.
use 5.014;
use strict;
use warnings;
use Text::Hunspell;
use List::Util qw(max);
use File::Find qw(find);
use Encode qw(decode_utf8);
use Perl::Tokenizer qw(perl_tokens);
use Text::JaroWinkler qw(strcmp95);
use Getopt::Long qw(GetOptions :config no_ignore_case);
binmode(STDOUT, ':utf8');
my $similarity = 90 / 100;
my $min_word_len = 6;
my $aggressive = 0;
my $non_word_split = 0;
my $scan_cats = 'com,str';
sub help {
my ($code) = @_;
my $p = sprintf('%.0f', $similarity * 100);
print <<"HELP";
usage: $0 [options] [files]
Options:
-m --minimum=f : minimum length for words (default: $min_word_len)
-p --percentage=f : minimum similarity percentage (default: $p)
-W --W-split! : split by non-word characters (default: by space)
-s --scan=s : categories of tokens to scan (default: "$scan_cats")
All the possible categories for --scan are:
pod : scan pod sections (including __END__)
str : scan strings (including here-documents)
com : scan comments
var : scan variable names
sub : scan subroutine declarations
bar : scan barewords (including subroutine/method calls)
all : scan all categories
Example:
$0 --scan=pod,com --percentage=75 /my/script.pl
HELP
exit($code);
}
my $percentage;
GetOptions(
'm|minimum=i' => \$min_word_len,
'p|percentage=f' => \$percentage,
's|scan=s' => \$scan_cats,
'W|W-split!' => \$non_word_split,
'h|help' => sub { help(0) },
)
or die("Error in command line arguments");
my $scan_pod = $scan_cats =~ /\bpod/;
my $scan_strings = $scan_cats =~ /\bstr/;
my $scan_comments = $scan_cats =~ /\bcom/;
my $scan_variables = $scan_cats =~ /\bvar/;
my $scan_subroutines = $scan_cats =~ /\bsub/;
my $scan_barewords = $scan_cats =~ /\bbar/;
if ($scan_cats =~ /\ball/) {
$scan_pod = 1;
$scan_strings = 1;
$scan_comments = 1;
$scan_variables = 1;
$scan_subroutines = 1;
$scan_barewords = 1;
}
if ( not $scan_pod
and not $scan_strings
and not $scan_comments
and not $scan_variables
and not $scan_subroutines
and not $scan_barewords) {
die "Invalid value for `--scan`: <<$scan_cats>>";
}
if (defined $percentage) {
$similarity = $percentage / 100;
}
#<<<
my $speller = Text::Hunspell->new(
"/usr/share/hunspell/en_US.aff",
"/usr/share/hunspell/en_US.dic",
) or die "Can't create the speller object: $!";
#>>>
@ARGV || help(2);
@ARGV = reverse(@ARGV);
while (@ARGV) {
my %seen;
my $file = pop @ARGV;
if (-d $file) {
find {
no_chdir => 1,
wanted => sub {
if (-f($_) and /\.p[lm]\z/) {
push @ARGV, $_;
}
},
} => $file;
next;
}
$file = decode_utf8($file);
open my $fh, '<:encoding(UTF-8)', $file or next;
local $SIG{__WARN__} = sub { };
my $code = eval { local $/; <$fh> } // next;
say "\n** Scanning: $file";
perl_tokens {
my ($token, $i, $j) = @_;
my $string;
if ($scan_strings) {
if ($token eq 'q_string') {
$string = substr($code, $i + 2, $j - $i - 3);
}
elsif ( $token eq 'qq_string'
or $token eq 'qw_string') {
$string = substr($code, $i + 3, $j - $i - 4);
}
elsif ( $token eq 'double_quoted_string'
or $token eq 'single_quoted_string') {
$string = substr($code, $i + 1, $j - $i - 2);
}
elsif ($token eq 'heredoc') {
$string = substr($code, $i, $j - $i);
$string =~ s/.*\K\R.*//s;
}
}
if ($scan_comments) {
if ($token eq 'comment') {
$string = substr($code, $i + 1, $j - $i - 1);
}
}
if ($scan_pod) {
if ( $token eq 'pod'
or $token eq 'data') {
$string = substr($code, $i, $j - $i);
}
}
if ($scan_variables) {
if ($token eq 'var_name') {
$string = substr($code, $i, $j - $i);
}
}
if ($scan_subroutines) {
if ($token eq 'sub_name') {
$string = substr($code, $i, $j - $i);
}
}
if ($scan_barewords) {
if ($token eq 'bare_word') {
$string = substr($code, $i, $j - $i);
}
}
if (defined $string) {
foreach my $word (
$non_word_split
? split(/[^\pL]+/, $string)
: split(' ', $string)
) {
if (!$non_word_split) {
$word =~ s/^[^\pL]+//;
$word =~ s/[^\pL]+\z//;
}
$word !~ /^[\pL]+\z/ and next;
length($word) < $min_word_len and next;
$seen{$word}++ and next;
$speller->check($word) and next;
my @suggestions = $speller->suggest($word);
if ( @suggestions
and lc($suggestions[0]) ne lc($word)
and $suggestions[0] !~ / /) {
my $score = strcmp95($suggestions[0], $word, max(length($suggestions[0]), length($word)));
if ($score >= $similarity) {
printf "[%.2f] %-20s => [%s]\n", $score, $word, join(', ', @suggestions);
}
}
}
}
} $code;
}
================================================
FILE: Analyzers/reptop.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 29 November 2011
# Edit: 03 November 2012
# https://github.com/trizen
# Find how many times each word exists in a file.
use 5.010;
use strict;
use warnings;
use open IO => ':utf8', ':std';
use Getopt::Long qw(GetOptions :config no_ignore_case);
my $word; # count for a particular word
my $regex; # split by regex
my $lowercase; # lowercase words
my $top = 0; # top of repeated words
my $length = 1; # mimimum length of a word
sub usage {
print <<"HELP";
usage: $0: [options] <file>
\nOptions:
-B : deactivate word match boundary (default: on)
-L : lowercase every word (default: off)
-w=s : show how many times a word repeats in the list
-t=i : show a top list of 'i' words (default: $top)
-l=i : minimum length of a valid word (default: $length)
-r=s : split by a regular expression (default: \\W+)\n
HELP
exit 0;
}
usage() unless @ARGV;
my $no_boundary;
GetOptions(
'word|w=s' => \$word,
'top|t=i' => \$top,
'regex|r=s' => \$regex,
'no-boundary|B' => \$no_boundary,
'L|lowercase!' => \$lowercase,
'length|l=i' => \$length,
'help|h|usage' => \&usage,
);
my $boundary = $no_boundary ? '' : '\\b';
$regex = defined $regex ? qr/$regex/ : qr/\W+/;
foreach my $file (grep { -f } @ARGV) {
my $file_content;
open my $fh, '<:encoding(UTF-8)', $file or die "Unable to open file '$file': $!\n";
read $fh, $file_content, -s $file;
close $fh;
if ($lowercase) {
$file_content = lc $file_content;
}
study $file_content;
if (defined($word)) {
my $i = 0;
++$i while $file_content =~ /$boundary\Q$word\E$boundary/go;
printf "Word '%s' repeats %d time%s in the list.\n", $word, $i, ($i == 1 ? '' : 's');
next;
}
my %uniq;
@uniq{split($regex, $file_content)} = ();
my @out;
foreach my $word (keys %uniq) {
next unless length $word >= $length;
my $i = 0;
++$i while $file_content =~ /$boundary\Q$word\E$boundary/g;
push @out, [$i, $word];
}
my $i = 0;
my @sorted = sort { $b->[0] <=> $a->[0] } @out;
my $max = length $sorted[0][0];
print "> $file\n";
foreach my $out (@sorted) {
printf "%*s -> %s\n", $max, $out->[0], $out->[1];
last if $top and ++$i == $top;
}
}
================================================
FILE: Analyzers/text_stats.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 15 June 2013
# https://github.com/trizen
#
## This script will compare the repetition of words from different authors.
#
## Example:
# perl text_stats.pl shake_1.txt shake_2.txt - twain_1.txt twain_2.txt
#
# The above example compares the files from two authors.
# If the first author written more words than the second one,
# the script will estimate the repetition of words from the second author
# as if it wrote the same amounts of words as the first author.
#
# You can provide as many authors as you want, separated by a dash argument (-).
use 5.010;
use strict;
use autodie;
use warnings;
use open IO => 'utf8';
use Text::Unidecode qw(unidecode);
my @authors = [];
while (@ARGV) {
my $file = shift @ARGV;
if ($file eq '-') {
push @authors, [];
next;
}
-f $file or do { warn "$0: '$file' is not a file!\n"; next };
push @{$authors[-1]}, $file;
}
my %table;
foreach my $author_files (@authors) {
foreach my $file (@{$author_files}) {
open my $fh, '<', $file;
while (<$fh>) {
s{[^\-'[:^punct:]]+}{ }g; # try to comment out this line
my @words = split(' ', unidecode(lc));
s{^[[:punct:]]+}{}, s{[[:punct:]]+\z}{} for @words;
/^\w/ && /\w\z/ && $table{$author_files}{$_}++ for @words;
}
}
}
my %data;
my @lens;
foreach my $i (0 .. $#authors) {
my $author = $authors[$i];
my $words = $table{$author};
while (my ($word, $cnt) = each %{$words}) {
$data{$word} //= [(0) x $i];
push @{$data{$word}}, $cnt;
}
push @lens, scalar keys %{$words};
}
my @ratios = (1);
foreach my $i (1 .. $#lens) {
push @ratios, $lens[$i] / $lens[$i-1];
}
print join(',', "WORD", (map { qq["AUTHOR $_"] } 1 .. $#authors + 1)), "\n";
foreach my $key (sort { $data{$b}[0] <=> $data{$a}[0] } keys %data) {
my @row;
foreach my $i (0 .. $#authors) {
push @row, sprintf("%0.f", ($data{$key}[$i] // 0) / $ratios[$i]);
}
print join(',', qq["$key"], @row), "\n";
}
================================================
FILE: Analyzers/unidecode_word_top.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 11 March 2013
# https://github.com/trizen
# usage: perl unidecode_word_top.pl [file]
use 5.010;
use strict;
use autodie;
use warnings;
use Text::Unidecode qw(unidecode);
open my $fh, '<:encoding(UTF-8)', shift;
my %table;
while (<$fh>) {
my @words = split(' ', unidecode(lc $_));
s{^[[:punct:]]+}{}, s{[[:punct:]]+\z}{} for @words;
/^\w/ && /\w\z/ && $table{$_}++ for @words;
}
foreach my $key (sort { $table{$b} <=> $table{$a} || $a cmp $b } keys %table) {
printf "%-50s%4s\n", $key, $table{$key};
}
================================================
FILE: Analyzers/wcer.pl
================================================
#!/usr/bin/perl
# Count words in a text file
# Coded by Trizen under GPL.
# usage: cat file.txt | perl wcer
# perl wcer file.txt
my $x = 0;
while (<>) {$x+=split' '}
print STDOUT "$x\n";
exit 0;
================================================
FILE: Analyzers/word_suffix_top.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 05 April 2015
# https://github.com/trizen
# Word suffix top
use 5.014;
use autodie;
use warnings;
use Text::Unidecode qw(unidecode);
my %top;
my $file = shift() // die "usage: $0 file [suffix len]\n";
my $i = shift() // 3;
my $total = 0;
{
open my $fh, '<:utf8', $file;
while (<$fh>) {
s/[_\W]+\z//;
if (/(\w{$i})\z/) {
++$top{lc(unidecode($1))};
++$total;
}
}
close $fh;
}
my $lonely = 0;
foreach my $key (sort { $top{$b} <=> $top{$a} or $a cmp $b } keys %top) {
printf("%s%10s%10.02f%%\n", $key, $top{$key}, $top{$key} / $total * 100);
++$lonely if ($top{$key} == 1);
}
printf "\n** Unique suffixes: %.02f%%\n", $lonely / $total * 100;
================================================
FILE: Audio/auto-mp3tags.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 15 August 2011
# Edit: 11 August 2019
# https://github.com/trizen
# Adds auto-tags to MP3 audio files in a given directory and its subdirectories.
use 5.010;
use strict;
use warnings;
use MP3::Tag;
use File::Find qw(find);
use File::Copy qw(copy);
use File::Temp qw(tempfile);
use File::Basename qw(basename);
use Encode qw(encode_utf8 decode_utf8);
my @files = grep { -e $_ } @ARGV;
die "Usage: $0 <dirs|files>\n" unless @files;
my @mp3_files;
find(\&wanted_files, @files);
sub wanted_files {
my $file = $File::Find::name;
push @mp3_files, $file if $file =~ /\.mp3\z/i;
}
foreach my $filename (@mp3_files) {
say "Processing: $filename";
my (undef, $tmpfile) = tempfile(basename($filename) . ' - XXXXXX', TMPDIR => 1);
unlink($tmpfile);
$tmpfile =~ s/ - .{6}\z//;
copy($filename, $tmpfile);
my $mp3 = 'MP3::Tag'->new($tmpfile);
my @fields = qw(artist album title comment);
$mp3->config(write_v24 => 1);
$mp3->autoinfo;
$mp3->update_tags({map { $_ => decode_utf8($mp3->$_) } @fields});
$mp3->close;
unlink($filename);
copy($tmpfile, $filename);
unlink($tmpfile);
}
================================================
FILE: Audio/group_audio_files.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 11 August 2019
# https://github.com/trizen
# Group MP3 files in directories based on their artist name.
# Example:
# Foo - abc.mp3
# Foo - xyz.mp3
# Both files will be moved in a new directory named "Foo".
# The directory "Foo" is created in the current working directory from which the script is executed.
use 5.016;
use strict;
use warnings;
binmode(STDOUT, ':utf8');
use Encode qw(decode_utf8);
use Text::Unidecode qw(unidecode);
use File::Find qw(find);
use File::Copy qw(move);
use File::Basename qw(basename);
use File::Spec::Functions qw(catdir catfile curdir);
use List::Util qw(sum);
use List::UtilsBy qw(max_by);
my $file_formats = qr{\.(?:mp3|mp4|webm|mkv|opus|ogg|oga)\z}i; # file formats
my (@files) = grep { -e $_ } @ARGV;
if (not @files) {
die "usage: $0 [dir]\n";
}
my @audio_files;
find(\&wanted_files, @files);
sub wanted_files {
my $file = $File::Find::name;
push @audio_files, $file if ($file =~ $file_formats);
}
if (@audio_files) {
say ":: Found ", scalar(@audio_files), " audio files...";
}
else {
say ":: No file found...";
}
my %groups;
foreach my $filename (@audio_files) {
my $basename = decode_utf8(basename($filename));
my $artist;
if ($basename =~ /^[\d\s.\-–]*(.+?) -/) {
$artist = $1;
}
elsif ($basename =~ /^[\d\s.\-–]*(.+?)-/) {
$artist = $1;
}
else {
next;
}
# Remove extra whitespace
$artist = join(' ', split(' ', $artist));
# Unidecode key and remove whitespace
my $key = join('', split(' ', unidecode(CORE::fc($artist))));
$key =~ s/[[:punct:]]+//g; # remove any punctuation characters
$key =~ s/\d+//g; # remove any digits
if ($key eq '' or $artist eq '') {
next;
}
push @{$groups{$key}{files}},
{
filepath => $filename,
basename => $basename,
};
++$groups{$key}{artists}{$artist};
}
while (my ($key, $group) = each %groups) {
my $files = $group->{files};
my $artists = $group->{artists};
sum(values %$artists) > 1 or next; # ignore single files
my $common_name = max_by { $artists->{$_} } sort { $a cmp $b } keys %$artists;
foreach my $file (@{$files}) {
my $group_dir = catdir(curdir(), $common_name);
if (not -e $group_dir) {
mkdir($group_dir) || do {
warn "[!] Can't create directory `$group_dir`: $!\n";
next;
};
}
if (not -d $group_dir) {
warn "[!] Not a directory: $group_dir\n";
next;
}
my $target = catfile($group_dir, $file->{basename});
if (not -e $target) {
say "[*] Moving file `$file->{basename}` into `$common_name` directory...";
move($file->{filepath}, $target) || warn "[!] Failed to move: $!\n";
}
}
}
================================================
FILE: Audio/mkv_audio_to_opus.pl
================================================
#!/usr/bin/perl
# Convert MKV audio files to OPUS files, in a given directory (and its subdirectories).
# Requires `ffmpeg` and `exiftool`.
use 5.036;
use File::Find qw(find);
use File::Temp qw(mktemp);
use File::Copy qw(move);
use File::Basename qw(dirname basename);
use File::Spec::Functions qw(catfile);
use Getopt::Long qw(GetOptions);
my $bitrate = 96;
sub usage ($exit_code = 0) {
print <<"EOT";
usage: $0 [options] [files | directories]
options:
-b --bitrate=i : output bitrate in kbps (default: $bitrate)
-h --help : display this message and exit
EOT
exit($exit_code);
}
GetOptions('b|bitrate=i' => \$bitrate,
'h|help' => sub { usage(0) },)
or die("Error in command line arguments");
sub is_mkv_audio ($file) {
my $res = `exiftool \Q$file\E`;
$? == 0 or return;
defined($res) or return;
$res =~ m{^MIME\s+Type\s*:\s*audio/x-matroska}mi;
}
sub convert ($file) {
my $tmpfile = mktemp("tempXXXXXXXXXXX") . '.opus';
say ":: Temporary file: $tmpfile";
system("ffmpeg", '-loglevel', 'warning', "-i", $file, "-b:a", $bitrate . "K", $tmpfile);
$? == 0 or do {
unlink($tmpfile);
return;
};
my $dir = dirname($file);
my $basename = basename($file) =~ s{\.\w+\z}{.opus}r;
my $new_file = catfile($dir, $basename);
unlink($file) or return;
say ":: Moving: $tmpfile -> $new_file";
move($tmpfile, $new_file);
}
my @dirs = @ARGV;
@dirs || usage(1);
find(
{
wanted => sub {
if (-f $_ and is_mkv_audio($_)) {
say ":: Converting: $_";
convert($_);
}
},
},
@dirs
);
================================================
FILE: Audio/recompress_audio_track.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 06 September 2023
# https://github.com/trizen
# Make video files smaller, by recompressing the audio track to the OPUS format (40kbps), using ffmpeg.
# Requires the following tools:
# ffmpeg
# exiftool
# Usage:
# perl recompress_audio_track.pl [files | directories]
use 5.036;
use File::Temp qw(mktemp);
use File::Find qw(find);
use File::Copy qw(move);
use File::Basename qw(dirname basename);
use File::Spec::Functions qw(catfile);
sub is_video_file ($file) {
my $res = `exiftool \Q$file\E`;
$? == 0 or return;
defined($res) or return;
$res =~ m{^MIME\s+Type\s*:\s*video/}mi;
}
sub recompress_audio_track ($video_file) {
say ":: Extracting audio track...";
my $orig_audio_file = mktemp("tempXXXXXXXXXXX") . '.mkv';
system("ffmpeg", "-loglevel", "warning", "-i", $video_file, "-vn", "-acodec", "copy", $orig_audio_file);
$? == 0 or do {
unlink($orig_audio_file);
return;
};
say ":: Recompressing audio track...";
my $new_audio_file = mktemp("tempXXXXXXXXXXX") . '.opus';
system("ffmpeg", "-loglevel", "warning", "-i", $orig_audio_file, "-vn", "-sn", "-dn", "-c:a", "libopus", "-b:a", "40K", $new_audio_file);
$? == 0 or do {
unlink($new_audio_file);
return;
};
# When the original file is smaller, keep the original file
if ((-s $orig_audio_file) <= (-s $new_audio_file)) {
say ":: The original audio track is smaller... Will keep it...";
unlink($new_audio_file);
$new_audio_file = $orig_audio_file;
}
say ":: Merging the recompressed audio track with the video...";
my $new_video_file = mktemp("tempXXXXXXXXXXX") . '.mkv';
system("ffmpeg", "-loglevel", "warning", "-i", $video_file, "-i", $new_audio_file,
"-map_metadata", "0", "-map", "0:v", "-map", "1:a", "-map", "0:s?", "-c", "copy", $new_video_file);
$? == 0 or do {
unlink($new_audio_file);
unlink($new_video_file);
return;
};
my $dir = dirname($video_file);
my $basename = basename($video_file) =~ s{\.\w+\z}{.mkv}r;
my $final_video_file = catfile($dir, $basename);
if ($final_video_file !~ /\.mkv\z/) {
$final_video_file .= '.mkv';
}
my $original_size = -s $orig_audio_file;
my $new_size = -s $new_audio_file;
printf(":: Saved: %.2f MB (%.2f%%)\n", ($original_size - $new_size) / 1024**2, ($original_size - $new_size) / $original_size * 100);
unlink($video_file);
unlink($new_audio_file);
unlink($orig_audio_file);
move($new_video_file, $final_video_file);
}
my @dirs = @ARGV;
if (not @dirs) {
die "usage: $0 [files | directories]\n";
}
find(
{
wanted => sub {
if (-f $_ and is_video_file($_)) {
say "\n:: Processing: $_";
recompress_audio_track($_);
}
},
},
@dirs
);
================================================
FILE: Audio/rem-mp3tags.pl
================================================
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 15 August 2011
# Edit: 11 August 2019
# https://github.com/trizen
# Removes tags of MP3 audio files in a given directory and its subdirectories.
use 5.010;
use strict;
use warnings;
use MP3::Tag;
use File::Find qw(find);
use File::Copy qw(copy);
use File::Temp qw(tempfile);
use File::Basename qw(basename);
my (@files) = grep { -e $_ } @ARGV;
die "Usage: $0 <dirs|files>\n" unless @files;
my $quiet = scalar grep { /^--?(?:q|quiet)\z/ } @ARGV;
my @mp3_files;
find(\&wanted_files, @files);
sub wanted_files {
my $file = $File::Find::name;
push @mp3_files, $file if $file =~ /\.mp3\z/i;
}
foreach my $filename (@mp3_files) {
my (undef, $tmpfile) = tempfile(basename($filename) . ' - XXXXXX', TMPDIR => 1);
unlink($tmpfile);
$tmpfile =~ s/ - .{6}\z//;
copy($filename, $tmpfile);
my $mp3 = 'MP3::Tag'->new($tmpfile);
$mp3->get_tags;
my $had_tags = 0;
if (exists $mp3->{'ID3v1'}) {
say "[ID3v1] Removing tag: $filename" unless $quiet;
$mp3->{'ID3v1'}->remove_tag;
$had_tags = 1;
}
if (exists $mp3->{'ID3v2'}) {
say "[ID3v2] Removing tag: $filename" unless $quiet;
$mp3->{'ID3v2'}->remove_tag;
$had_tags = 1;
}
$mp3->close;
if ($had_tags) {
unlink($filename);
copy($tmpfile, $filename);
}
unlink($tmpfile);
}
================================================
FILE: Audio/wave-cmp.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 22 March 2015
# Website: https://github.com/trizen
# Find similar audio files by comparing their waveforms.
# Review:
# https://trizenx.blogspot.com/2015/03/similar-audio-files.html
#
## The waveform is processed block by block:
# _________________________________________
# |_____|_____|_____|_____|_____|_____|_____|
# |_____|_____|_____|_____|_____|_____|_____|
# |_____|_____|_____|_____|_____|_____|_____|
# |_____|_____|_____|_____|_____|_____|_____|
#
# Each block has a distinct number of white pixels, which are collected
# inside an array and constitute the unique fingerprint of the waveform.
#
# Now, each block value is compared with the corresponding value
# of another fingerprint. If the difference from all blocks is within
# the allowed deviation, then the audio files are marked as similar.
#
# In the end, the similar files are reported to the standard output.
# Requirements:
# - ffmpeg: https://ffmpeg.org/
# - wav2png: https://github.com/beschulz/wav2png
use utf8;
use 5.010;
use strict;
use autodie;
use warnings;
require GD;
GD::Image->trueColor(1);
require GDBM_File;
use List::Util qw(sum);
use Getopt::Long qw(GetOptions);
use File::Find qw(find);
use File::Temp qw(tempdir);
use File::Path qw(make_path);
use File::Spec::Functions qw(catfile catdir);
require Digest::MD5;
my $ctx = Digest::MD5->new;
my $pkgname = 'wave-cmp';
my $version = 0.01;
my $deviation = 5;
my ($width, $height) = (1800, 300);
my ($div_x, $div_y) = (10, 2);
sub help {
my ($code) = @_;
print <<"EOT";
usage: $0 [options] [dirs|files]
=> Waveform generation
-w --width=i : width of the waveform (default: $width)
-h --height=i : height of the waveform (default: $height)
=> Waveform processing
-x --x-div=i : divisions along the X-axis (default: $div_x)
-y --y-div=i : divisions along the Y-axis (default: $div_y)
-d --deviation=i : tolerance deviation value (default: $deviation)
--help : print this message and exit
--version : print the version number and exit
example:
$0 --deviation=6 ~/Music
EOT
exit($code);
}
sub version {
print "$pkgname $version\n";
exit 0;
}
GetOptions(
'w|width=i' => \$width,
'h|height=i' => \$height,
'x|x-div=i' => \$div_x,
'y|y-div=i' => \$div_y,
'd|deviation=i' => \$deviation,
'help' => sub { help(0) },
'v|version' => \&version,
)
or die("Error in command line arguments");
my $sq_x = int($width / $div_x);
my $sq_y = int($height / $div_y);
my $limit_x = $width - $sq_x;
my $limit_y = int($height / 2) - $sq_y; # analyze only the first half
# Source: https://en.wikipedia.org/wiki/Audio_file_format#List_of_formats
my @audio_formats = qw(
3gp
act
aiff
aac
amr
au
awb
dct
dss
flac
gsm
m4a
m4p
mp3
mpc
ogg oga
opus
ra rm
raw
sln
tta
vox
wav
wma
wv
webm
);
my $audio_formats_re = do {
local $" = '|';
qr/\.(?:@audio_formats)\z/i;
};
my $home_dir =
$ENV{HOME}
|| $ENV{LOGDIR}
|| (getpwuid($<))[7]
|| `echo -n ~`;
my $xdg_config_home = catdir($home_dir, '.config');
my $cache_dir = catdir($xdg_config_home, $pkgname);
my $cache_db = catfile($cache_dir, 'fp.db');
if (not -d $cache_dir) {
make_path($cache_dir);
}
my $tmpdir = tempdir(CLEANUP => 1);
tie my %db, 'GDBM_File', $cache_db, &GDBM_File::GDBM_WRCREAT, 0640;
#
#-- execute the ffmpeg and wave2png commands and return the waveform PNG data
#
sub generate_waveform {
my ($file, $output) = @_;
#<<<
# Using sox (currently broken)
# return scalar `sox \Q$file\E -q --norm -V0 --multi-threaded -t wav --encoding signed-integer - | wav2png -w $width -h $height -f ffffffff -b 00000000 -o /dev/stdout /dev/stdin`;
#>>>
my $tmpfile = catfile($tmpdir, $file . '.wav');
system("ffmpeg", "-loglevel", "quiet", "-i", $file, $tmpfile);
$? == 0 or return;
my $waveform = `wav2png -w $width -h $height -f 000000ff -b ffffff00 -o /dev/stdout \Q$tmpfile\E`;
unlink($tmpfile);
return $waveform;
}
#
#-- return the md5 hex digest of the content of a file
#
sub md5_file {
my ($file) = @_;
open my $fh, '<:raw', $file;
$ctx->addfile($fh);
$ctx->hexdigest;
}
#
#-- take image data as input and return a fingerprint array ref
#
sub generate_fingerprint {
my ($image_data) = @_;
$image_data eq '' and return;
state %rgb_cache; # cache the RGB values of pixels
my @fingerprint;
my $image = GD::Image->new($image_data) // return;
for (my $i = 0 ; $i <= $limit_x ; $i += $sq_x) {
for (my $j = 0 ; $j <= $limit_y ; $j += $sq_y) {
my $fill = 0;
foreach my $x ($i .. $i + $sq_x - 1) {
foreach my $y ($j .. $j + $sq_y - 1) {
my $index = $image->getPixel($x, $y);
my $rgb = $rgb_cache{$index} //= [$image->rgb($index)];
$fill++ if $rgb->[0] == 255; # check only the value of red
}
}
push @fingerprint, $fill;
}
}
return \@fingerprint;
}
#
#-- fetch or generate the fingerprint for a given audio file
#
sub fingerprint {
my ($audio_file) = @_;
state $local_cache = {};
return $local_cache->{$audio_file}
if exists $local_cache->{$audio_file};
my $md5 = md5_file($audio_file);
my $key = "$width/$height/$div_x/$div_y/$md5";
if (not exists $db{$key}) {
my $image_data = generate_waveform($audio_file) // return;
my $fingerprint = generate_fingerprint($image_data) // return;
$db{$key} = join(':', @{$fingerprint});
return ($local_cache->{$audio_file} = $fingerprint);
}
$local_cache->{$audio_file} //= [split /:/, $db{$key}];
}
#
#-- compare two fingerprints and return true if they are alike
#
sub alike_fingerprints {
my ($a1, $a2) = @_;
foreach my $i (0 .. $#{$a1}) {
my $value = abs($a1->[$i] - $a2->[$i]) / ($sq_x * $sq_y) * 100;
return if $value > $deviation;
}
return 1;
}
#
#-- compare two audio files and return true if they are alike
#
sub alike_files {
my ($file1, $file2) = @_;
my $fp1 = fingerprint($file1) // return;
my $fp2 = fingerprint($file2) // return;
alike_fingerprints($fp1, $fp2);
}
#
#-- find and call $code with a group of similar audio files
#
sub find_similar_audio_files {
my $code = shift;
my @files;
find {
no_chdir => 1,
wanted => sub {
/$audio_formats_re/ || return;
lstat;
(-f _) && (not -l _) && push @files, $_;
}
} => @_;
my %groups;
my %seen;
my $limit = $#files;
foreach my $i (0 .. $limit) {
foreach my $j ($i + 1 .. $limit) {
next if $seen{$files[$j]};
if (alike_files($files[$i], $files[$j])) {
$groups{$i} //= [$files[$i]];
$seen{$files[$j]}++;
push @{$groups{$i}}, $files[$j];
}
}
if (exists $groups{$i}) {
$code->(delete $groups{$i});
}
}
}
#
#-- print a group of files followed by an horizontal line
#
sub print_group {
my ($group) = @_;
foreach my $file (sort { (lc($a) cmp lc($b)) || ($a cmp $b) } @{$group}) {
say $file;
}
say "-" x 80;
}
@ARGV || help(2);
find_similar_audio_files(\&print_group, @ARGV);
================================================
FILE: Audio/wave-cmp2.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 22 March 2015
# Edit: 04 September 2015
# Website: https://github.com/trizen
# Find similar audio files by comparing their waveforms.
# Review:
# https://trizenx.blogspot.com/2015/03/similar-audio-files.html
# Requirements:
# - ffmpeg: https://ffmpeg.org
# - wav2png: https://github.com/beschulz/wav2png
use utf8;
use 5.022;
use strict;
use autodie;
use warnings;
use experimental 'bitwise';
require GD;
GD::Image->trueColor(1);
require GDBM_File;
use List::Util qw(sum);
use Getopt::Long qw(GetOptions);
use File::Find qw(find);
use File::Temp qw(tempdir);
use File::Path qw(make_path);
use File::Spec::Functions qw(catfile catdir);
require Digest::MD5;
my $ctx = Digest::MD5->new;
my $pkgname = 'wave-cmp2';
my $version = 0.02;
# Mark files as similar based on this percentage
my $percentage = 75;
# The size of the waveform
my ($width, $height) = (1800, 300);
sub help {
my ($code) = @_;
print <<"EOT";
usage: $0 [options] [dirs|files]
=> Waveform generation
-w --width=i : width of the waveform (default: $width)
-h --height=i : height of the waveform (default: $height)
=> Waveform processing
-p --percentage=i : minimum percentage of similarity (default: $percentage)
--help : print this message and exit
--version : print the version number and exit
example:
$0 --percentage=80 ~/Music
EOT
exit($code);
}
sub version {
print "$pkgname $version\n";
exit 0;
}
GetOptions(
'w|width=i' => \$width,
'h|height=i' => \$height,
'p|percentage=i' => \$percentage,
'help' => sub { help(0) },
'v|version' => \&version,
)
or die("Error in command line arguments");
my $size = $width * $height;
# Source: https://en.wikipedia.org/wiki/Audio_file_format#List_of_formats
my @audio_formats = qw(
3gp
act
aiff
aac
amr
au
awb
dct
dss
flac
gsm
m4a
m4p
mp3
mpc
ogg oga
opus
ra rm
raw
sln
tta
vox
wav
wma
wv
webm
);
my $audio_formats_re = do {
local $" = '|';
qr/\.(?:@audio_formats)\z/i;
};
my $home_dir =
$ENV{HOME}
|| $ENV{LOGDIR}
|| (getpwuid($<))[7]
|| `echo -n ~`;
my $xdg_config_home = catdir($home_dir, '.config');
my $cache_dir = catdir($xdg_config_home, $pkgname);
my $cache_db = catfile($cache_dir, 'fp.db');
if (not -d $cache_dir) {
make_path($cache_dir);
}
my $tmpdir = tempdir(CLEANUP => 1);
tie my %db, 'GDBM_File', $cache_db, &GDBM_File::GDBM_WRCREAT, 0640;
#
#-- execute the ffmpeg and wave2png commands and return the waveform PNG data
#
sub generate_waveform {
my ($file, $output) = @_;
#<<<
# Using sox (currently broken)
# return scalar `sox \Q$file\E -q --norm -V0 --multi-threaded -t wav --encoding signed-integer - | wav2png -w $width -h $height -f ffffffff -b 00000000 -o /dev/stdout /dev/stdin`;
#>>>
my $tmpfile = catfile($tmpdir, $file . '.wav');
system("ffmpeg", "-loglevel", "quiet", "-i", $file, $tmpfile);
$? == 0 or return;
my $waveform = `wav2png -w $width -h $height -f 000000ff -b ffffff00 -o /dev/stdout \Q$tmpfile\E`;
unlink($tmpfile);
return $waveform;
}
#
#-- return the md5 hex digest of the content of a file
#
sub md5_file {
my ($file) = @_;
open my $fh, '<:raw', $file;
$ctx->addfile($fh);
$ctx->hexdigest;
}
#<<<
#
#-- compare two fingerprints and return the similarity percentage
#
sub alike_percentage {
((($_[0] ^. $_[1]) =~ tr/\0//) / $size)**2 * 100;
}
#>>>
#
#-- compute the average value of a pixel
#
sub avg {
($_[0] + $_[1] + $_[2]) / 3;
}
#
#-- take image data as input and return the fingerprint as string
#
sub generate_fingerprint {
my ($image_data) = @_;
$image_data eq '' and return;
my $img = GD::Image->new($image_data) // return;
my @averages;
foreach my $y (0 .. $height - 1) {
foreach my $x (0 .. $width - 1) {
push @averages, avg($img->rgb($img->getPixel($x, $y)));
}
}
my $avg = sum(@averages) / @averages;
join('', map { $_ < $avg ? 1 : 0 } @averages);
}
#
#-- fetch or generate the fingerprint for a given audio file
#
sub fingerprint {
my ($audio_file) = @_;
state $local_cache = {};
return $local_cache->{$audio_file}
if exists $local_cache->{$audio_file};
my $md5 = md5_file($audio_file);
my $key = "$width/$height/$md5";
if (not exists $db{$key}) {
my $image_data = generate_waveform($audio_file) // return;
my $fingerprint = generate_fingerprint($image_data) // return;
$db{$key} = pack('B*', $fingerprint);
return ($local_cache->{$audio_file} = $fingerprint);
}
$local_cache->{$audio_file} //= unpack('B*', $db{$key});
}
#
#-- find and call $code with a group of similar audio files
#
sub find_similar_audio_files(&@) {
my $callback = shift;
my @files;
find {
no_chdir => 1,
wanted => sub {
(/$audio_formats_re/o && -f) || return;
push @files,
{
fingerprint => fingerprint($_) // return,
filename => $_,
};
}
} => @_;
#
## Populate the %alike hash
#
my %alike;
foreach my $i (0 .. $#files - 1) {
for (my $j = $i + 1 ; $j <= $#files ; $j++) {
my $p = alike_percentage($files[$i]{fingerprint}, $files[$j]{fingerprint});
if ($p >= $percentage) {
$alike{$files[$i]{filename}}{$files[$j]{filename}} = $p;
$alike{$files[$j]{filename}}{$files[$i]{filename}} = $p;
}
}
}
#
## Group the files
#
my @alike;
foreach my $root (
map { $_->[0] }
sort { ($a->[1] <=> $b->[1]) || ($b->[2] <=> $a->[2]) }
map {
my $keys = keys(%{$alike{$_}});
my $avg = sum(values(%{$alike{$_}})) / $keys;
[$_, $keys, $avg]
}
keys %alike
) {
my @group = keys(%{$alike{$root}});
if (@group) {
my $avg = 0;
$avg += delete($alike{$_}{$root}) for @group;
push @alike, {score => $avg / @group, files => [$root, @group]};
}
}
#
## Callback each group
#
my %seen;
foreach my $group (sort { $b->{score} <=> $a->{score} } @alike) {
(@{$group->{files}} == grep { $seen{$_}++ } @{$group->{files}}) and next;
$callback->($group->{score}, $group->{files});
}
return 1;
}
@ARGV || help(2);
find_similar_audio_files {
my ($score, $files) = @_;
printf("=> Similarity: %.0f%%\n", $score), say join("\n", @{$files});
say "-" x 80;
}
@ARGV;
================================================
FILE: Benchmarks/array_range_vs_shift.pl
================================================
#!/usr/bin/perl
use 5.014;
use Benchmark qw(cmpthese);
package Foo {
sub new {
bless {}, __PACKAGE__;
}
sub call_me { }
sub bar {
$_[0]->call_me(@_[1 .. $#_]);
}
sub baz {
shift(@_)->call_me(@_);
}
}
my $obj = Foo->new();
cmpthese(
-1,
{
with_shift => sub {
$obj->baz(1, 2, 3, 4, 5);
$obj->baz();
$obj->baz(1);
$obj->baz(1, 2);
},
with_range => sub {
$obj->bar(1, 2, 3, 4, 5);
$obj->bar();
$obj->bar(1);
$obj->bar(1, 2);
},
}
);
__END__
Rate with_range with_shift
with_range 721308/s -- -33%
with_shift 1071850/s 49% --
================================================
FILE: Benchmarks/compression_algorithms.pl
================================================
#!/usr/bin/perl
# Rough performance comparison of some compression modules on a given file given as an argument.
use 5.010;
use strict;
use warnings;
use Time::HiRes qw(gettimeofday tv_interval);
my $data_str = do {
open(my $fh, '<:raw', $ARGV[0] // $0)
or die "Can't open file <<$ARGV[0]>> for reading: $!";
local $/;
<$fh>;
};
say "Raw : ", length($data_str);
say '';
eval {
my $t0 = [gettimeofday];
require IO::Compress::Gzip;
IO::Compress::Gzip::gzip(\$data_str, \my $data_gzip);
say "Gzip: ", length($data_gzip);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Bzip2;
IO::Compress::Bzip2::bzip2(\$data_str, \my $data_bzip2);
say "Bzip: ", length($data_bzip2);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::RawDeflate;
IO::Compress::RawDeflate::rawdeflate(\$data_str, \my $data_raw_deflate);
say "RDef: ", length($data_raw_deflate);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Deflate;
IO::Compress::Deflate::deflate(\$data_str, \my $data_deflate);
say "Defl: ", length($data_deflate);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Zip;
IO::Compress::Zip::zip(\$data_str, \my $data_zip);
say "Zip : ", length($data_zip);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Lzf;
IO::Compress::Lzf::lzf(\$data_str, \my $data_lzf);
say "Lzf : ", length($data_lzf);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Lzip;
IO::Compress::Lzip::lzip(\$data_str, \my $data_lzip);
say "Lzip: ", length($data_lzip);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Lzop;
IO::Compress::Lzop::lzop(\$data_str, \my $data_lzop);
say "Lzop: ", length($data_lzop);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
eval {
my $t0 = [gettimeofday];
require IO::Compress::Zstd;
IO::Compress::Zstd::zstd(\$data_str, \my $data_zstd);
say "Zstd: ", length($data_zstd);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
0 && eval {
my $t0 = [gettimeofday];
require IO::Compress::Brotli;
my $data_bro = IO::Compress::Brotli::bro($data_str);
say "Brot: ", length($data_bro);
say "Time: ", tv_interval($t0, [gettimeofday]);
say '';
};
================================================
FILE: Benchmarks/json_vs_storable.pl
================================================
#!/usr/bin/perl
# Speed comparison of JSON::XS vs Storable.
# Result:
# Storable is significantly faster for both encoding and decoding of data.
use 5.014;
use strict;
use warnings;
use Storable qw(freeze thaw);
use JSON::XS qw(encode_json decode_json);
use LWP::Simple qw(get);
use Benchmark qw(cmpthese);
my $info = {
content => get("https://github.com/"),
description => "GitHub is where people build software. More than 73 million people use GitHub to discover, fork, and contribute to over 200 million projects.",
id => "2df61d3f",
keywords => undef,
score => 2,
title => "This is a test",
url => "https://github.com/",
};
my $storable = freeze($info);
my $json = encode_json($info);
say "# Decoding speed:\n";
cmpthese(
-1,
{
json => sub {
my $data = decode_json($json);
},
storable => sub {
my $data = thaw($storable);
},
}
);
say "\n# Encoding speed:\n";
cmpthese(
-1,
{
json => sub {
my $data = encode_json($info);
},
storable => sub {
my $data = freeze($info);
},
}
);
__END__
# Decoding speed:
Rate json storable
json 2327/s -- -94%
storable 41533/s 1685% --
# Encoding speed:
Rate json storable
json 1541/s -- -93%
storable 21721/s 1309% --
================================================
FILE: Benchmarks/schwartzian_transform.pl
================================================
#!/usr/bin/perl
# Performance comparison of Schwartzian transform.
# See also:
# https://en.wikipedia.org/wiki/Schwartzian_transform
use 5.010;
use Benchmark qw(cmpthese);
my @alpha = map { chr($_) } 32 .. 127;
my @arr = (
map {
join('', map { $alpha[rand @alpha] } 1 .. 140)
} 1 .. 100
);
cmpthese(
-1,
{
schwartz => sub {
my @sorted = map { $_->[1] }
sort { $a->[0] cmp $b->[0] }
map { [lc($_), $_] } @arr;
@sorted;
},
without_schwartz => sub {
my @sorted = sort { lc($a) cmp lc($b) } @arr;
@sorted;
},
}
);
__END__
Rate without_schwartz schwartz
without_schwartz 4403/s -- -53%
schwartz 9309/s 111% --
================================================
FILE: Benchmarks/types_of_variables.pl
================================================
#!/usr/bin/perl
# Performance comparison between `state`, `my` and global variables.
use 5.010;
use Benchmark qw(cmpthese);
cmpthese(
-1,
{
my => sub {
my $x = rand(1);
$x + 1;
},
state => sub {
state $x;
$x = rand(1);
$x + 1;
},
global => sub {
$main::global = rand(1);
$main::global + 1;
}
}
);
__END__
Rate my global state
my 12105605/s -- -17% -44%
global 14563555/s 20% -- -32%
state 21462081/s 77% 47% --
================================================
FILE: Book tools/rosettacode_to_markdown.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 24 April 2015
# Edit: 09 December 2023
# Website: https://github.com/trizen
# Extract markdown code from each task for a given programming language.
use utf8;
use 5.020;
use strict;
use autodie;
use warnings;
use experimental qw(signatures);
use Text::Tabs qw(expand);
use Encode qw(decode_utf8);
use Getopt::Long qw(GetOptions);
use File::Path qw(make_path);
use LWP::UserAgent::Cached qw();
use URI::Escape qw(uri_unescape uri_escape);
use HTML::Entities qw(decode_entities);
use File::Spec::Functions qw(catfile catdir);
binmode(STDOUT, ':utf8');
binmode(STDERR, ':utf8');
sub escape_markdown ($t) {
$t =~ s{([*_`])}{\\$1}g;
return $t;
}
sub escape_lang ($s) {
$s =~ s/\s/_/gr; # replace whitespace with underscores
}
sub _ulist ($s) {
$s =~ s{<li>(.*?)</li>}{* $1\n}gsr;
}
sub _olist ($s) {
my $i = 1;
$s =~ s{<li>(.*?)</li>}{$i++ . '. ' . "$1\n"}egsr;
}
sub tags_to_markdown ($t, $escape = 0) {
my $out = '';
until ($t =~ /\G\z/gc) {
if ($t =~ m{\G<br\h*/\h*>}gc) {
$out .= "\n";
}
elsif ($t =~ m{\G<b>(.*?)</b>}gcs) {
$out .= "**" . tags_to_markdown($1, 1) . "**";
}
elsif ($t =~ m{\G<i>(.*?)</i>}gcs) {
$out .= "*" . tags_to_markdown($1, 1) . "*";
}
elsif ($t =~ m{\G<code>(.*?)</code>}gcs) {
$out .= "`" . decode_entities($1) . "`";
}
elsif ($t =~ m{\G<tt>(.*?)</tt>}gcs) {
$out .= "`" . decode_entities($1) . "`";
}
elsif ($t =~ m{\G<a\b.*? href="(.*?)".*?>(.*?)</a>}gcs) {
my ($url, $label) = ($1, $2);
if ($url =~ m{^/}) {
$url = 'https://rosettacode.org' . $url;
}
$label = tags_to_markdown($label);
$out .= "[$label]($url)";
}
elsif ($t =~ m{\G(<img\b.*? src="/mw/.*?".*?/>)}gc) {
my $html = $1;
$html =~ s{ src="\K/mw/}{https://rosettacode.org/mw/};
$html =~ s{ srcset=".*?"}{};
$out .= $html;
}
elsif ($t =~ m{\G<span><span class="mwe-math-mathml-inline mwe-math-mathml-a11y"}gc) {
$t =~ m{\G.*?</span>}gsc;
if ($t =~ m{\G<meta class="mwe-math-fallback-image-inline".*? url\('(/mw/index\.php\?(?:.*?))'\).*?/></span>}gc) {
$out .= ' . ')';
}
else {
warn "[!] Failed to parse math meta class!\n";
}
}
elsif ($t =~ m{\G<ul>(.*?)</ul>}gcs) {
$out .= _ulist(tags_to_markdown($1, 1));
}
elsif ($t =~ m{\G<ol>(.*?)</ol>}gcs) {
$out .= _olist(tags_to_markdown($1, 1));
}
elsif ($t =~ /\G([^<]+)/gc) {
$out .= $escape ? escape_markdown($1) : $1;
}
elsif ($t =~ /\G(.)/gcs) {
$out .= $escape ? escape_markdown($1) : $1;
}
}
return $out;
}
sub strip_tags ($s) {
$s =~ s/<.*?>//gsr; # remove HTML tags
}
sub strip_space ($s) {
unpack('A*', $s =~ s/^\s+//r); # remove leading and trailing whitespace
}
sub extract_tasks ($content, $lang) {
my $i = index($content, qq{<h2>Pages in category "$lang"</h2>});
if ($i == -1) {
warn "[!] Can't find any tasks for language: <$lang>!\n";
return;
}
my $tasks_content = substr($content, $i);
my @tasks;
while ($tasks_content =~ m{<a href="/wiki/(.+?)" title=".+?">(.+?)</a></li>}g) {
my ($task, $label) = ($1, $2);
last if $task eq 'Special:Categories';
push @tasks,
{
name => decode_utf8(uri_unescape($task)),
title => $label,
};
}
return \@tasks;
}
sub extract_all_tasks ($main_url, $path_url, $lang) {
my $lwp_uc = LWP::UserAgent->new(
show_progress => 1,
agent => '',
timeout => 60,
);
my $tasks_url = $main_url . $path_url;
my $resp = $lwp_uc->get($tasks_url);
$resp->is_success || die $resp->status_line;
my $content = $resp->decoded_content;
my $tasks = extract_tasks($content, $lang);
my @all_tasks = @$tasks;
if ($content =~ m{<a href="([^"]+)" title="[^"]+">next page</a>}) {
push @all_tasks, __SUB__->($main_url, $1, $lang);
}
return @all_tasks;
}
sub extract_lang ($content, $lang, $lang_alias = $lang) {
my $header = sub {
qq{<span class="mw-headline" id="$_[0]">};
};
my $i = index($content, $header->($lang));
# Try with the language escaped
if ($i == -1) {
$i = index($content, $header->(escape_lang($lang)));
}
# Try with the language alias
if ($i == -1) {
$i = index($content, $header->($lang_alias));
}
# Try with the language alias escaped
if ($i == -1) {
$i = index($content, $header->(escape_lang($lang_alias)));
}
# Give up
if ($i == -1) {
warn "[!] Can't find language: <$lang>\n";
return;
}
my $j = index($content, '<h2>', $i);
if ($j == -1) {
$j = index($content, '<div class="printfooter">', $i);
}
if ($j == -1) {
state $x = 0;
if (++$x <= 3) {
warn "[!] Position `j` will point at the end of the page...\n";
}
$j = length($content);
}
$i = index($content, '</h2>', $i);
if ($i == -1) {
warn "[!] Can't find the end of the header!\n";
return;
}
$i += 5; # past the end of the header
my $part = strip_space(substr($content, $i, $j - $i));
# remove <script> tags
$part =~ s{<script\b.+?</script>}{}gsi;
# replace [email protected] with 'email@example.net'
$part =~ s{<a class="__cf_email__".+?</a>}{email\@example.net}gsi;
my @data;
until ($part =~ /\G\z/gc) {
if ($part =~ m{\G<pre class="(.+?) highlighted_source">(.+)</pre>}gc) { # old way
push @data,
{
code => {
lang => $1,
data => $2,
}
};
}
elsif ($part =~ m{\G<div class="[^"]*mw-highlight-lang-(\S+)[^"]*" dir="ltr"><pre>(.*?)</pre>}sgc) { # new way
push @data,
{
code => {
lang => $1,
data => $2,
}
};
}
elsif ($part =~ m{\G<h([1-4])>(.*?)</h[1-4]>}sgc) {
push @data,
{
header => {
n => $1,
data => $2,
}
};
}
elsif ($part =~ m{\G<p>(.*?)</p>}sgc) {
push @data,
{
text => {
tag => 'p',
data => $1,
},
};
}
elsif ($part =~ m{\G<pre\b[^>]*>(.*?)</pre>}sgc) {
push @data,
{
text => {
tag => 'pre',
data => $1,
}
};
}
elsif ($part =~ m{\G(.)}sgc) {
@data && exists($data[-1]{unknown})
? ($data[-1]{unknown}{data} .= $1)
: (push @data, {unknown => {data => $1}});
}
}
return \@data;
}
sub to_html ($lang_data) {
my $text = '';
foreach my $item (@{$lang_data}) {
if (exists $item->{text}) {
$text .= qq{<$item->{text}{tag}>$item->{text}{data}</$item->{text}{tag}>};
}
elsif (exists $item->{code}) {
$text .= qq{<pre class="lang $item->{code}{lang}">$item->{code}{data}</pre>};
}
}
return $text;
}
sub to_markdown ($lang_data) {
my $text = '';
my $has_output = 1;
foreach my $item (@{$lang_data}) {
if (exists $item->{header}) {
my $n = $item->{header}{n};
my $data = $item->{header}{data};
my $t = strip_tags(tags_to_markdown(strip_space($data), 1));
$t =~ s/\[\[edit\].*//s;
$text .= "\n\n" . ('#' x $n) . ' ' . $t . "\n\n";
}
elsif (exists $item->{text}) {
my $data = $item->{text}{data};
my $tag = $item->{text}{tag};
if ($tag eq 'p') {
my $t = tags_to_markdown(strip_space($data), 1);
$text .= "\n\n" . $t . "\n\n";
$has_output = 1;
}
elsif ($tag eq 'pre') {
my $t = decode_entities($data);
$t =~ s/^(?:\R)+//;
$t =~ s/(?:\R)+\z//;
$t = join("\n", expand(split(/\R/, $t)));
$text .= "\n#### Output:" if !$has_output;
$text .= "\n```\n$t\n```\n";
}
}
elsif (exists $item->{code}) {
my $code = decode_entities(strip_tags(tags_to_markdown($item->{code}{data})));
my $lang = $item->{code}{lang};
$code =~ s/\[(\w+)\]\(https?:.*?\)/$1/g;
$code =~ s{(?:\R)+\z}{};
$text .= "```$lang\n$code\n```\n";
$has_output = 0;
}
}
return strip_space($text);
}
sub write_to_file ($base_dir, $name, $markdown, $overwrite = 0) {
# Remove parenthesis
$name =~ tr/()//d;
# Substitute bad characters
#$name =~ tr{-A-Za-z0-9[]'*_/À-ÿ}{_}c;
$name =~ s{[^\pL\pN\[\]'*/\-]+}{ }g;
# Replace multiple spaces with a single underscore
$name = join('_', split(' ', $name));
my $char = uc(substr($name, 0, 1));
my $dir = catdir($base_dir, $char);
# Remove directory paths from name (if any)
if ($name =~ s{^(.*)/}{}) {
my $dirname = $1;
$dir = catdir($dir, map { $_ eq 'Sorting_Algorithms' ? 'Sorting_algorithms' : $_ } split(/\//, $dirname));
}
# Create directory if it doesn't exists
if (not -d $dir) {
make_path($dir) or do {
warn "[!] Can't create path `$dir`: $!\n";
return;
};
}
my $file = catfile($dir, "$name.md");
if (not $overwrite) {
return 1 if -e $file; # Don't overwrite existent files
}
say "** Creating file: $file";
open(my $fh, '>:encoding(UTF-8)', $file) or do {
warn "[!] Can't create file `$file`: $!";
return;
};
print {$fh} $markdown;
close $fh;
}
#
## MAIN
#
my $cache_dir = 'cache';
my $lang = 'Sidef';
my $lang_alias = undef;
my $overwrite = 0;
my $base_dir = 'programming_tasks';
my $main_url = 'https://rosettacode.org';
sub usage {
print <<"EOT";
usage: $0 [options]
options:
--lang=s : the programming language name (default: $lang)
--base-dir=s : where to save the files (default: $base_dir)
--overwrite! : overwrite existent files (default: $overwrite)
--cache-dir=s : cache directory (default: $cache_dir)
--main-url=s : main URL (default: $main_url)
--help : print this message and exit
example:
$0 --lang=Perl --base-dir=perl_tasks
EOT
exit;
}
GetOptions(
'cache-dir=s' => \$cache_dir,
'L|language=s' => \$lang,
'base-dir=s' => \$base_dir,
'main-url=s' => \$main_url,
'overwrite!' => \$overwrite,
'help' => \&usage,
)
or die "[!] Error in command line arguments!";
if (not -d $cache_dir) {
mkdir($cache_dir);
}
my $lwp = LWP::UserAgent::Cached->new(
timeout => 60,
show_progress => 1,
agent => '',
cache_dir => $cache_dir,
nocache_if => sub {
my ($response) = @_;
my $code = $response->code;
return 1 if ($code >= 300); # do not cache any bad response
return 1 if ($code == 401); # don't cache an unauthorized response
return 1 if ($response->request->method ne 'GET'); # cache only GET requests
return;
},
);
{
my $accepted_encodings = HTTP::Message::decodable();
$lwp->default_header('Accept-Encoding' => $accepted_encodings);
require LWP::ConnCache;
my $cache = LWP::ConnCache->new;
$cache->total_capacity(undef); # no limit
$lwp->conn_cache($cache);
}
my @tasks = extract_all_tasks($main_url, '/wiki/' . escape_lang($lang), $lang);
sub my_uri_escape ($path) {
$path =~ s/([?'+])/uri_escape($1)/egr;
}
foreach my $task (@tasks) {
my $name = $task->{name};
my $title = $task->{title};
my $url = "$main_url/wiki/" . my_uri_escape($name);
my $resp = $lwp->get($url);
if ($resp->is_success) {
my $content = $resp->decoded_content;
my $lang_data = extract_lang($content, $lang, $lang_alias) // do { $lwp->uncache; next };
my $header = "[1]: $url\n\n" . "# [$title][1]\n\n";
my $markdown = $header . to_markdown($lang_data) . "\n";
write_to_file($base_dir, $name, $markdown, $overwrite);
}
else {
warn "[" . $resp->status_line . "] Can't fetch: $url\n";
}
}
================================================
FILE: Book tools/update_summary.pl
================================================
#!/usr/bin/perl
# Author: Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 24 April 2015
# Website: https://github.com/trizen
# Add a given directory to a given section in SUMMARY.md (for gitbooks)
use 5.014;
use strict;
use autodie;
use warnings;
use Cwd qw(getcwd);
use File::Basename qw(basename dirname);
use File::Spec::Functions qw(rel2abs);
sub add_section {
my ($name, $section, $file) = @_;
my ($before, $middle, $after);
open my $fh, '<', $file;
while (defined(my $line = <$fh>)) {
if ($line =~ /^(\*\h+\Q$name\E)\h*$/ || $line =~ m{^(\*\h+\[\Q$name\E\](?:\(.*\))?)\h*$}) {
$middle = "$1\n";
say "** Found section: <<<$1>>>";
while (defined(my $line = <$fh>)) {
if ($line =~ /^\S/) {
$after = $line;
}
}
}
else {
if (defined $after) {
$after .= $line;
}
else {
$before .= $line;
}
}
}
close $fh;
open my $out_fh, '>', $file;
print {$out_fh} $before . $middle . $section . $after;
close $out_fh;
}
my $summary_file = 'SUMMARY.md';
my $main_dir = 'programming_tasks';
my $section_name = 'Programming tasks';
{
my @root;
sub make_section {
my ($name, $dir, $spaces) = @_;
my $cwd = getcwd();
chdir $dir;
my @files = map { {name => $_, path => rel2abs($_)} } glob('*'); # sorting for free
chdir $cwd;
my $make_section_url = sub {
my ($name) = @_;
join('/', basename($main_dir), @root, $name);
};
my %ignored;
my $section = '';
foreach my $file (@files) {
my $title = $file->{name} =~ s/_/ /gr;
if (-d $file->{path}) {
if (-e "$file->{path}.md") {
my $url_path = $make_section_url->("$file->{name}.md");
$section .= (' ' x $spaces) . "* [\u$title]($url_path)\n";
$ignored{"$file->{name}.md"}++; # ignore this file later
}
else {
$section .= (' ' x $spaces) . "* $title\n";
}
push @root, $file->{name};
$section .= make_section($file->{name}, $file->{path}, $spaces + 4);
}
else {
next if $dir eq $main_dir;
next if $ignored{$file->{name}};
my $naked_name = $file->{name} =~ s/\.md\z//ir;
my $naked_title = $title =~ s/\.md\z//ir;
my $url_path = $make_section_url->($file->{name});
$section .= (' ' x $spaces) . "* [\u$naked_title]($url_path)\n";
}
}
pop @root;
return $section;
}
}
my $section = make_section($section_name, $main_dir, 3);
my $section_content = add_section($section_name, $section, $summary_file);
say "** All done!";
================================================
FILE: Compression/High-level/ablz_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 17 June 2023
# Edit: 31 July 2024
# https://github.com/trizen
# Compress/decompress files using Adaptive Binary Coding, followed by LZ77 compression (LZ4-like) on bits + Bzip2 on the literals.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'ABLZ',
VERSION => '0.01',
FORMAT => 'ablz',
CHUNK_SIZE => 1 << 18, # higher value = better compression
};
local $Compression::Util::LZ_MIN_LEN = 8 * 4; # minimum match length
local $Compression::Util::LZ_MAX_LEN = 1 << 15; # maximum match length
local $Compression::Util::LZ_MAX_CHAIN_LEN = 64; # higher value = better compression
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my $bits = unpack('B*', abc_encode(string2symbols($chunk)));
my ($uncompressed, $distances, $lengths, $matches) = lz77_encode($bits);
my $ubits = pack('C*', @$uncompressed);
my $rem = length($ubits) % 8;
my $str = pack('B*', $ubits);
print $out_fh chr($rem);
print $out_fh mrl_compress_symbolic($str);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances, \&mrl_compress_symbolic);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $rem = ord getc $fh;
my $str = symbols2string(mrl_decompress_symbolic($fh));
my $ubits = unpack('B*', $str);
if ($rem != 0) {
$ubits = substr($ubits, 0, -(8 - $rem));
}
my $uncompressed = [unpack('C*', $ubits)];
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh, \&mrl_decompress_symbolic);
my $bits = lz77_decode($uncompressed, $distances, $lengths, $matches);
print $out_fh symbols2string(abc_decode(pack('B*', $bits)));
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bbwr_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 04 July 2024
# https://github.com/trizen
# Compress/decompress files using Binary Burrows-Wheeler Transform (BWT) + Binary Variable Run-Length Encoding.
# References:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Data Compression (Summer 2023) - Lecture 5 - Basic Techniques
# https://youtube.com/watch?v=TdFWb8mL5Gk
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BBWR',
VERSION => '0.01',
FORMAT => 'bbwr',
CHUNK_SIZE => 1 << 13, # larger values == better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my $bits = unpack('B*', $chunk);
my $vrle1 = binary_vrl_encode($bits);
if (length($vrle1) < length($bits)) {
printf "Doing early VLR, saving %s bits\n", length($bits) - length($vrle1);
print $out_fh chr(1);
}
else {
print $out_fh chr(0);
$vrle1 = $bits;
}
my ($bwt, $idx) = bwt_encode($vrle1);
my $vrle2 = binary_vrl_encode($bwt);
say "BWT index: $idx";
print $out_fh pack('N', $idx);
print $out_fh pack('N', length($vrle2));
print $out_fh pack('B*', $vrle2);
}
sub decompression ($fh, $out_fh) {
my $compressed_byte = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $bits_len = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
say "BWT index = $idx";
my $bwt = binary_vrl_decode(read_bits($fh, $bits_len));
my $data = bwt_decode($bwt, $idx);
if ($compressed_byte == 1) {
$data = binary_vrl_decode($data);
}
print $out_fh pack('B*', $data);
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/blzss2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 17 June 2023
# Edit: 29 July 2024
# https://github.com/trizen
# Compress/decompress files using LZ77 compression (LZ4-like) on bits + Huffman coding + Bzip2 on the literals.
# Good at compressing data where there are patterns on bits, but not at byte boundaries (e.g.: variable-bit encoded data).
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BLZSS2',
VERSION => '0.01',
FORMAT => 'blzss2',
CHUNK_SIZE => 1 << 18, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my $bits = unpack('B*', $chunk);
my ($uncompressed, $distances, $lengths, $matches) = do {
local $Compression::Util::LZ_MIN_LEN = 8 * 4; # minimum match length
local $Compression::Util::LZ_MAX_LEN = 1 << 15; # maximum match length
local $Compression::Util::LZ_MAX_CHAIN_LEN = 64; # higher value = better compression
lz77_encode($bits);
};
my $ubits = pack('C*', @$uncompressed);
my $rem = length($ubits) % 8;
my $str = pack('B*', $ubits);
print $out_fh chr($rem);
print $out_fh mrl_compress_symbolic($str, \&lzss_compress_symbolic);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances, \&mrl_compress_symbolic);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $rem = ord getc $fh;
my $str = symbols2string(mrl_decompress_symbolic($fh, \&lzss_decompress_symbolic));
my $ubits = unpack('B*', $str);
if ($rem != 0) {
$ubits = substr($ubits, 0, -(8 - $rem));
}
my $uncompressed = [unpack('C*', $ubits)];
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh, \&mrl_decompress_symbolic);
my $bits = lz77_decode($uncompressed, $distances, $lengths, $matches);
print $out_fh pack('B*', $bits);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/blzss_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 17 June 2023
# Edit: 25 July 2024
# https://github.com/trizen
# Compress/decompress files using LZ77 compression (LZ4-like) on bits + Huffman coding.
# Good at compressing data where there are patterns on bits, but not at byte boundaries (e.g.: variable-bit encoded data).
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BLZSS',
VERSION => '0.01',
FORMAT => 'blzss',
CHUNK_SIZE => 1 << 18, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my $bits = unpack('B*', $chunk);
my ($uncompressed, $distances, $lengths, $matches) = do {
local $Compression::Util::LZ_MIN_LEN = 8 * 5; # minimum match length
local $Compression::Util::LZ_MAX_LEN = 1 << 15; # maximum match length
local $Compression::Util::LZ_MAX_CHAIN_LEN = 64; # higher value = better compression
lz77_encode($bits);
};
my $ubits = pack('C*', @$uncompressed);
my $rem = length($ubits) % 8;
my $str = pack('B*', $ubits);
print $out_fh chr($rem);
print $out_fh mrl_compress_symbolic($str, \&lzss_compress_symbolic);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances, \&mrl_compress_symbolic);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $rem = ord getc $fh;
my $str = symbols2string(mrl_decompress_symbolic($fh, \&lzss_decompress_symbolic));
my $ubits = unpack('B*', $str);
if ($rem != 0) {
$ubits = substr($ubits, 0, -(8 - $rem));
}
my $uncompressed = [unpack('C*', $ubits)];
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh, \&mrl_decompress_symbolic);
my $bits = lz77_decode($uncompressed, $distances, $lengths, $matches);
print $out_fh pack('B*', $bits);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/brlzss_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 17 June 2023
# Edit: 25 July 2024
# https://github.com/trizen
# Compress/decompress files using Binary RLE + LZ77 compression (LZ4-like) + Huffman coding.
# Good at compressing data where there are patterns on bits, but not at byte boundaries (e.g.: variable-bit encoded data).
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BRLZSS',
VERSION => '0.01',
FORMAT => 'brlzss',
CHUNK_SIZE => 1 << 18, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my $bits = unpack('B*', $chunk);
my $rle = binary_vrl_encode($bits);
if (length($rle) >= length($bits)) {
print $out_fh chr(0);
printf("Without binary VRLE: %s >= %s\n", length($rle), length($bits));
$rle = $bits;
}
else {
print $out_fh chr(1);
printf("With binary VRLE: %s < %s\n", length($rle), length($bits));
}
my ($uncompressed, $distances, $lengths, $matches) = do {
local $Compression::Util::LZ_MIN_LEN = 8 * 3; # minimum match length
local $Compression::Util::LZ_MAX_LEN = 1 << 15; # maximum match length
local $Compression::Util::LZ_MAX_CHAIN_LEN = 64; # higher value = better compression
lz77_encode($rle);
};
my $ubits = pack('C*', @$uncompressed);
print $out_fh chr(length($ubits) % 8);
my $str = pack('B*', $ubits);
print $out_fh mrl_compress_symbolic($str, \&lzss_compress_symbolic);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances, \&mrl_compress_symbolic);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $with_vrle = ord getc($fh);
my $rem = ord getc($fh);
my $str = symbols2string(mrl_decompress_symbolic($fh, \&lzss_decompress_symbolic));
my $ubits = unpack('B*', $str);
if ($rem != 0) {
$ubits = substr($ubits, 0, -(8 - $rem));
}
my $uncompressed = [unpack('C*', $ubits)];
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh, \&mrl_decompress_symbolic);
my $rle = lz77_decode($uncompressed, $distances, $lengths, $matches);
my $bits = $with_vrle ? binary_vrl_decode($rle) : $rle;
print $out_fh pack('B*', $bits);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwac_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 14 June 2023
# Edit: 13 April 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-Front Transform + Run-length encoding + Arithmetic Coding.
# References:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Basic arithmetic coder in C++
# https://github.com/billbird/arith32
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWAC',
VERSION => '0.02',
FORMAT => 'bwac',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(2);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
print $out_fh bwt_compress($chunk, \&create_ac_entry);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
print $out_fh bwt_decompress($fh, \&decode_ac_entry);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwad_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 14 June 2023
# Edit: 21 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-Front Transform + Run-length encoding + Adaptive Arithmetic Coding (in fixed bits).
# References:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Basic arithmetic coder in C++
# https://github.com/billbird/arith32
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWAD',
VERSION => '0.02',
FORMAT => 'bwad',
CHUNK_SIZE => 1 << 17,
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(2);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
print $out_fh bwt_compress($chunk, \&create_adaptive_ac_entry);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
print $out_fh bwt_decompress($fh, \&decode_adaptive_ac_entry);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlz2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 13 April 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + LZ77 compression + Symbolic Bzip2.
# Encoding the literals and the pointers using a DEFLATE-like approach.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZ2',
VERSION => '0.01',
FORMAT => 'bwlz2',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my @chunk_bytes = unpack('C*', $chunk);
my $data = pack('C*', @{rle4_encode(\@chunk_bytes, 254)});
my ($bwt, $idx) = bwt_encode($data);
my @bytes = unpack('C*', $bwt);
my @alphabet = sort { $a <=> $b } uniq(@bytes);
my $enc_bytes = mtf_encode(\@bytes, \@alphabet);
if (max(@$enc_bytes) < 255) {
print $out_fh chr(1);
$enc_bytes = zrle_encode($enc_bytes);
}
else {
print $out_fh chr(0);
$enc_bytes = rle4_encode($enc_bytes);
}
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet(\@alphabet);
print $out_fh lzss_compress(pack('C*', @$enc_bytes), \&bwt_compress_symbolic);
}
sub decompression ($fh, $out_fh) {
my $rle_encoded = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $alphabet = decode_alphabet($fh);
my $dec = lzss_decompress($fh, \&bwt_decompress_symbolic);
my $bytes = [unpack('C*', $dec)];
if ($rle_encoded) {
$bytes = zrle_decode($bytes);
}
else {
$bytes = rle4_decode($bytes);
}
$bytes = mtf_decode($bytes, $alphabet);
print $out_fh symbols2string(rle4_decode(string2symbols(bwt_decode(pack('C*', @$bytes), $idx))));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the files
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlz3_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 02 May 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-front transform (MTF) + ZRLE + LZHD compression.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZ3',
VERSION => '0.01',
FORMAT => 'bwlz3',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my $lzb = do {
local $Compression::Util::LZ_MIN_LEN = 512;
lzb_compress($chunk);
};
my @chunk_bytes = unpack('C*', $lzb);
my $data = rle4_encode(\@chunk_bytes, scalar(@chunk_bytes));
my ($bwt, $idx) = bwt_encode_symbolic($data);
my ($enc_bytes, $alphabet) = mtf_encode($bwt);
$enc_bytes = zrle_encode($enc_bytes);
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet($alphabet);
print $out_fh lz77_compress_symbolic($enc_bytes);
}
sub decompression ($fh, $out_fh) {
my $idx = bytes2int($fh, 4);
my $alphabet = decode_alphabet($fh);
my $symbols = lz77_decompress_symbolic($fh);
$symbols = zrle_decode($symbols);
$symbols = mtf_decode($symbols, $alphabet);
print $out_fh lzb_decompress(symbols2string(rle4_decode(bwt_decode_symbolic($symbols, $idx))));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the files
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlz_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 21 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-front transform (MTF) + LZ77 compression (LZSS) + Huffman coding.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZ',
VERSION => '0.05',
FORMAT => 'bwlz',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(5);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my @chunk_bytes = unpack('C*', $chunk);
my $data = pack('C*', @{rle4_encode(\@chunk_bytes, 254)});
my ($bwt, $idx) = bwt_encode($data);
my @bytes = unpack('C*', $bwt);
my @alphabet = sort { $a <=> $b } uniq(@bytes);
my $enc_bytes = mtf_encode(\@bytes, \@alphabet);
if (max(@$enc_bytes) < 255) {
print $out_fh chr(1);
$enc_bytes = zrle_encode($enc_bytes);
}
else {
print $out_fh chr(0);
$enc_bytes = rle4_encode($enc_bytes);
}
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet(\@alphabet);
print $out_fh lzss_compress(pack('C*', @$enc_bytes));
}
sub decompression ($fh, $out_fh) {
my $rle_encoded = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $alphabet = decode_alphabet($fh);
my $dec = lzss_decompress($fh);
my $bytes = [unpack('C*', $dec)];
if ($rle_encoded) {
$bytes = zrle_decode($bytes);
}
else {
$bytes = rle4_decode($bytes);
}
$bytes = mtf_decode($bytes, $alphabet);
print $out_fh symbols2string(rle4_decode(string2symbols(bwt_decode(pack('C*', @$bytes), $idx))));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the files
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlza2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 19 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + LZ77 compression (LZHD variant) + Arithmetic Coding (in fixed bits).
# Encoding the distances using a DEFLATE-like approach.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Basic arithmetic coder in C++
# https://github.com/billbird/arith32
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(uniq max);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZA2',
VERSION => '0.01',
FORMAT => 'bwlza2',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub lzad_compression ($chunk, $out_fh) {
my ($uncompressed, $distances, $lengths, $matches) = lz77_encode($chunk);
my $est_ratio = length($chunk) / (4 * scalar(@$uncompressed));
say(scalar(@$uncompressed), ' -> ', $est_ratio);
print $out_fh create_ac_entry($uncompressed);
print $out_fh create_ac_entry($lengths);
print $out_fh create_ac_entry($matches);
print $out_fh obh_encode($distances, \&create_ac_entry);
}
sub lzad_decompression ($fh) {
my $uncompressed = decode_ac_entry($fh);
my $lengths = decode_ac_entry($fh);
my $matches = decode_ac_entry($fh);
my $distances = obh_decode($fh, \&decode_ac_entry);
return lz77_decode($uncompressed, $distances, $lengths, $matches);
}
sub compression ($chunk, $out_fh) {
my @chunk_bytes = unpack('C*', $chunk);
my $data = pack('C*', @{rle4_encode(\@chunk_bytes, 254)});
my ($bwt, $idx) = bwt_encode($data);
my @bytes = unpack('C*', $bwt);
my @alphabet = sort { $a <=> $b } uniq(@bytes);
my $enc_bytes = mtf_encode(\@bytes, [@alphabet]);
if (max(@$enc_bytes) < 255) {
print $out_fh chr(1);
$enc_bytes = zrle_encode($enc_bytes);
}
else {
print $out_fh chr(0);
$enc_bytes = rle4_encode($enc_bytes);
}
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet(\@alphabet);
lzad_compression(pack('C*', @$enc_bytes), $out_fh);
}
sub decompression ($fh, $out_fh) {
my $rle_encoded = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $alphabet = decode_alphabet($fh);
my $bytes = string2symbols(lzad_decompression($fh));
if ($rle_encoded) {
$bytes = zrle_decode($bytes);
}
else {
$bytes = rle4_decode($bytes);
}
$bytes = mtf_decode($bytes, [@$alphabet]);
print $out_fh pack('C*', @{rle4_decode([unpack('C*', bwt_decode(pack('C*', @$bytes), $idx))])});
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the output file
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlza_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 21 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-front transform (MTF) + LZ77 compression (LZSS) + Arithmetic Coding (in fixed bits).
# Encoding the literals and the pointers using a DEFLATE-like approach.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Basic arithmetic coder in C++
# https://github.com/billbird/arith32
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZA',
VERSION => '0.03',
FORMAT => 'bwlza',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(3);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my @chunk_bytes = unpack('C*', $chunk);
my $data = pack('C*', @{rle4_encode(\@chunk_bytes, 254)});
my ($bwt, $idx) = bwt_encode($data);
my @bytes = unpack('C*', $bwt);
my @alphabet = sort { $a <=> $b } uniq(@bytes);
my $enc_bytes = mtf_encode(\@bytes, \@alphabet);
if (max(@$enc_bytes) < 255) {
print $out_fh chr(1);
$enc_bytes = zrle_encode($enc_bytes);
}
else {
print $out_fh chr(0);
$enc_bytes = rle4_encode($enc_bytes);
}
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet(\@alphabet);
print $out_fh lzss_compress(pack('C*', @$enc_bytes), \&create_ac_entry);
}
sub decompression ($fh, $out_fh) {
my $rle_encoded = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $alphabet = decode_alphabet($fh);
my $dec = lzss_decompress($fh, \&decode_ac_entry);
my $bytes = [unpack('C*', $dec)];
if ($rle_encoded) {
$bytes = zrle_decode($bytes);
}
else {
$bytes = rle4_decode($bytes);
}
$bytes = mtf_decode($bytes, $alphabet);
print $out_fh symbols2string(rle4_decode(string2symbols(bwt_decode(pack('C*', @$bytes), $idx))));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the output file
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlzad2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 19 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-front transform (MTF) + LZ77 compression (LZHD variant) + Adaptive Arithmetic Coding (in fixed bits).
# Encoding the distances using a DEFLATE-like approach.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Basic arithmetic coder in C++
# https://github.com/billbird/arith32
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZAD2',
VERSION => '0.01',
FORMAT => 'bwlzad2',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub lzhd_compression ($chunk, $out_fh) {
my ($uncompressed, $distances, $lengths, $matches) = lz77_encode($chunk);
my $est_ratio = length($chunk) / (4 * scalar(@$uncompressed));
say(scalar(@$uncompressed), ' -> ', $est_ratio);
print $out_fh create_ac_entry($uncompressed);
print $out_fh create_ac_entry($lengths);
print $out_fh create_ac_entry($matches);
print $out_fh abc_encode($distances);
}
sub lzhd_decompression ($fh) {
my $uncompressed = decode_ac_entry($fh);
my $lengths = decode_ac_entry($fh);
my $matches = decode_ac_entry($fh);
my $distances = abc_decode($fh);
return lz77_decode($uncompressed, $distances, $lengths, $matches);
}
sub compression ($chunk, $out_fh) {
my @chunk_bytes = unpack('C*', $chunk);
my $data = pack('C*', @{rle4_encode(\@chunk_bytes)});
my ($bwt, $idx) = bwt_encode($data);
my @bytes = unpack('C*', $bwt);
my @alphabet = sort { $a <=> $b } uniq(@bytes);
my $enc_bytes = mtf_encode(\@bytes, [@alphabet]);
if (max(@$enc_bytes) < 255) {
print $out_fh chr(1);
$enc_bytes = zrle_encode($enc_bytes);
}
else {
print $out_fh chr(0);
$enc_bytes = rle4_encode($enc_bytes);
}
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet(\@alphabet);
lzhd_compression(pack('C*', @$enc_bytes), $out_fh);
}
sub decompression ($fh, $out_fh) {
my $rle_encoded = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $alphabet = decode_alphabet($fh);
my $bytes = string2symbols(lzhd_decompression($fh));
if ($rle_encoded) {
$bytes = zrle_decode($bytes);
}
else {
$bytes = rle4_decode($bytes);
}
$bytes = mtf_decode($bytes, [@$alphabet]);
print $out_fh symbols2string(rle4_decode(string2symbols(bwt_decode(pack('C*', @$bytes), $idx))));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the output file
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlzad_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 07 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-front transform (MTF) + LZ77 compression (LZSS) + Adaptive Arithmetic Coding (in fixed bits).
# Encoding the literals and the pointers using a DEFLATE-like approach.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
#
# Basic arithmetic coder in C++
# https://github.com/billbird/arith32
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZAD',
VERSION => '0.01',
FORMAT => 'bwlzad',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Arithmetic Coding settings
use constant BITS => 32;
use constant MAX => oct('0b' . ('1' x BITS));
use constant INITIAL_FREQ => 1;
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my @chunk_bytes = unpack('C*', $chunk);
my $data = pack('C*', @{rle4_encode(\@chunk_bytes, 254)});
my ($bwt, $idx) = bwt_encode($data);
my @bytes = unpack('C*', $bwt);
my @alphabet = sort { $a <=> $b } uniq(@bytes);
my $enc_bytes = mtf_encode(\@bytes, \@alphabet);
if (max(@$enc_bytes) < 255) {
print $out_fh chr(1);
$enc_bytes = zrle_encode($enc_bytes);
}
else {
print $out_fh chr(0);
$enc_bytes = rle4_encode($enc_bytes);
}
print $out_fh pack('N', $idx);
print $out_fh encode_alphabet(\@alphabet);
print $out_fh lzss_compress(pack('C*', @$enc_bytes), \&create_adaptive_ac_entry);
}
sub decompression ($fh, $out_fh) {
my $rle_encoded = ord(getc($fh) // die "error");
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $alphabet = decode_alphabet($fh);
my $bytes = [unpack('C*', lzss_decompress($fh, \&decode_adaptive_ac_entry))];
if ($rle_encoded) {
$bytes = zrle_decode($bytes);
}
else {
$bytes = rle4_decode($bytes);
}
$bytes = mtf_decode($bytes, $alphabet);
print $out_fh symbols2string(rle4_decode(string2symbols(bwt_decode(pack('C*', @$bytes), $idx))));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the output file
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlzb_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 03 June 2024
# https://github.com/trizen
# Compress/decompress files using byte-aligned LZ77 compression (LZSS) + Burrows-Wheeler Transform (BWT) + Move-to-front transform (MTF) + Huffman coding.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use List::Util qw(max uniq);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZB',
VERSION => '0.01',
FORMAT => 'bwlzb',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(5);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
local $Compression::Util::LZ_MIN_LEN = 64;
my $rle4 = symbols2string(rle4_encode(string2symbols($chunk)));
my $lzb = lzb_compress($rle4);
my ($bwt, $idx) = bwt_encode($lzb);
my ($mtf, $alphabet) = mtf_encode(string2symbols($bwt));
my $rle = zrle_encode($mtf);
my $enc = pack('N', $idx) . encode_alphabet($alphabet) . create_huffman_entry($rle);
print $out_fh $enc;
}
sub decompression ($fh, $out_fh) {
my $idx = bytes2int($fh, 4);
my $alphabet = decode_alphabet($fh);
my $rle = decode_huffman_entry($fh);
my $mtf = zrle_decode($rle);
my $bwt = symbols2string(mtf_decode($mtf, $alphabet));
my $lzb = bwt_decode($bwt, $idx);
my $rle4 = lzb_decompress($lzb);
my $data = symbols2string(rle4_decode(string2symbols($rle4)));
print $out_fh $data;
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the output file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the files
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlzhd2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 December 2022
# Edit: 25 July 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler transform (BWT) + Run-length Encoding (RLE) + LZ77 compression (LZ4-like) + Move-to-front + Huffman coding.
# Encoding the distances/indices using a DEFLATE-like approach.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZHD2',
VERSION => '0.01',
FORMAT => 'bwlzhd2',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my $rle4 = rle4_encode([unpack('C*', $chunk)]);
my ($bwt, $idx) = bwt_encode(pack('C*', @$rle4));
say "BWT index = $idx";
my ($uncompressed, $distances, $lengths, $matches) = lz77_encode($bwt);
my $est_ratio = length($chunk) / (4 * scalar(@$uncompressed));
say(scalar(@$uncompressed), ' -> ', $est_ratio);
print $out_fh pack('N', $idx);
print $out_fh mrl_compress_symbolic($uncompressed);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances, \&mrl_compress_symbolic);
}
sub decompression ($fh, $out_fh) {
my $idx = unpack('N', join('', map { getc($fh) // return undef } 1 .. 4));
my $uncompressed = mrl_decompress_symbolic($fh);
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh, \&mrl_decompress_symbolic);
my $bwt = lz77_decode($uncompressed, $distances, $lengths, $matches);
my @rle4 = unpack('C*', bwt_decode($bwt, $idx));
print $out_fh symbols2string(rle4_decode(\@rle4));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlzhd_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 December 2022
# Edit: 19 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler transform (BWT) + Run-length Encoding (RLE) + LZ77 compression (LZHD variant) + Huffman coding.
# Encoding the distances/indices using a DEFLATE-like approach.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZHD',
VERSION => '0.02',
FORMAT => 'bwlzhd',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(2);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my $rle4 = rle4_encode([unpack('C*', $chunk)]);
my ($bwt, $idx) = bwt_encode(pack('C*', @$rle4));
$bwt = pack('C*', @{rle4_encode([unpack('C*', $bwt)])});
say "BWT index = $idx";
my ($uncompressed, $distances, $lengths, $matches) = lz77_encode($bwt);
my $est_ratio = length($chunk) / (4 * scalar(@$uncompressed));
say(scalar(@$uncompressed), ' -> ', $est_ratio);
print $out_fh pack('N', $idx);
print $out_fh mrl_compress_symbolic($uncompressed);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances);
}
sub decompression ($fh, $out_fh) {
my $idx = unpack('N', join('', map { getc($fh) // return undef } 1 .. 4));
my $uncompressed = mrl_decompress_symbolic($fh);
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh);
my $rle4 = lz77_decode($uncompressed, $distances, $lengths, $matches);
my $bwt = symbols2string(rle4_decode(string2symbols($rle4)));
my @rle4 = unpack('C*', bwt_decode($bwt, $idx));
print $out_fh symbols2string(rle4_decode(\@rle4));
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwlzss_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 June 2023
# Edit: 21 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + LZ77 compression (LZSS) + Huffman coding.
# References:
# Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip)
# https://youtube.com/watch?v=SJPvNi4HrWQ
#
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWLZSS',
VERSION => '0.01',
FORMAT => 'bwlzss',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub compression ($chunk, $out_fh) {
my $rle4 = rle4_encode([unpack('C*', $chunk)]);
my ($bwt, $idx) = bwt_encode(pack('C*', @$rle4));
print $out_fh pack('N', $idx);
print $out_fh lzss_compress($bwt, \&mrl_compress_symbolic);
}
sub decompression ($fh, $out_fh) {
my $idx = unpack('N', join('', map { getc($fh) // die "error" } 1 .. 4));
my $bwt = lzss_decompress($fh, \&mrl_decompress_symbolic);
my $rle4 = bwt_decode($bwt, $idx);
my $data = rle4_decode([unpack('C*', $rle4)]);
print $out_fh pack('C*', @$data);
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
compression($chunk, $out_fh);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
decompression($fh, $out_fh);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwrl2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 10 September 2023
# Edit: 13 April 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Variable Run-Length encoding + Huffman coding.
# Reference:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWRL2',
VERSION => '0.01',
FORMAT => 'bwrl2',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub VLR_encoding ($bytes) {
my $uncompressed = '';
my $bitstream = '';
my $rle = run_length($bytes);
foreach my $cv (@$rle) {
my ($c, $v) = @$cv;
$uncompressed .= chr($c);
if ($v == 1) {
$bitstream .= '0';
}
else {
my $t = sprintf('%b', $v);
$bitstream .= join('', '1' x (length($t) - 1), '0', substr($t, 1));
}
}
return ($uncompressed, pack('B*', $bitstream));
}
sub VLR_decoding ($uncompressed, $bits_fh) {
my $decoded = '';
my $buffer = '';
foreach my $c (@$uncompressed) {
my $bl = 0;
while (read_bit($bits_fh, \$buffer) == 1) {
++$bl;
}
if ($bl > 0) {
$decoded .= chr($c) x oct('0b1' . join('', map { read_bit($bits_fh, \$buffer) } 1 .. $bl));
}
else {
$decoded .= chr($c);
}
}
return $decoded;
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my ($bwt, $idx) = bwt_encode(symbols2string(rle4_encode($chunk)));
my ($uncompressed, $lengths) = VLR_encoding(string2symbols($bwt));
print $out_fh pack('N', $idx);
print $out_fh mrl_compress_symbolic($uncompressed, sub ($s) { lzss_compress_symbolic($s, \&mrl_compress_symbolic) });
print $out_fh create_huffman_entry(rle4_encode(string2symbols($lengths)));
}
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $idx = bytes2int($fh, 4);
my $uncompressed = mrl_decompress_symbolic($fh, sub ($s) { lzss_decompress_symbolic($s, \&mrl_decompress_symbolic) });
open my $len_fh, '+>:raw', \my $lengths;
print $len_fh symbols2string(rle4_decode(decode_huffman_entry($fh)));
seek($len_fh, 0, 0);
my $dec = VLR_decoding($uncompressed, $len_fh);
print $out_fh symbols2string(rle4_decode(bwt_decode($dec, $idx)));
}
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwrm2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 10 September 2023
# Edit: 13 April 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Run-Length encoding + MTF + ZRLE + Bzip2 on lengths.
# Reference:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWRM2',
VERSION => '0.01',
FORMAT => 'bwrm2',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub VLR_encoding ($bytes) {
my @lengths;
my @uncompressed;
my $rle = run_length($bytes, 256);
foreach my $cv (@$rle) {
my ($c, $v) = @$cv;
push @uncompressed, $c;
push @lengths, $v - 1;
}
return (\@uncompressed, \@lengths);
}
sub VLR_decoding ($uncompressed, $lengths) {
my $decoded = '';
foreach my $i (0 .. $#{$uncompressed}) {
my $c = $uncompressed->[$i];
my $len = $lengths->[$i];
if ($len > 0) {
$decoded .= chr($c) x ($len + 1);
}
else {
$decoded .= chr($c);
}
}
return $decoded;
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my ($bwt, $idx) = bwt_encode(symbols2string(rle4_encode($chunk)));
my ($uncompressed, $lengths) = VLR_encoding(string2symbols($bwt));
print $out_fh pack('N', $idx);
print $out_fh mrl_compress_symbolic($uncompressed, \&lzss_compress_symbolic);
print $out_fh bwt_compress(pack('C*', @$lengths));
}
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $idx = unpack('N', join('', map { getc($fh) // die "decompression error" } 1 .. 4));
my $uncompressed = mrl_decompress_symbolic($fh, \&lzss_decompress_symbolic);
my $lengths = bwt_decompress($fh);
my $dec = VLR_decoding($uncompressed, string2symbols($lengths));
print $out_fh symbols2string(rle4_decode(bwt_decode($dec, $idx)));
}
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwrm_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 10 September 2023
# Edit: 13 April 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Run-Length encoding + MTF + ZRLE.
# Reference:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWRM',
VERSION => '0.01',
FORMAT => 'bwrm',
CHUNK_SIZE => 1 << 17, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
sub VLR_encoding ($bytes) {
my @lengths;
my @uncompressed;
my $rle = run_length($bytes);
foreach my $cv (@$rle) {
my ($c, $v) = @$cv;
push @uncompressed, $c;
push @lengths, $v - 1;
}
return (\@uncompressed, \@lengths);
}
sub VLR_decoding ($uncompressed, $lengths) {
my $decoded = '';
foreach my $i (0 .. $#{$uncompressed}) {
my $c = $uncompressed->[$i];
my $len = $lengths->[$i];
if ($len > 0) {
$decoded .= chr($c) x ($len + 1);
}
else {
$decoded .= chr($c);
}
}
return $decoded;
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my ($bwt, $idx) = bwt_encode(symbols2string(rle4_encode($chunk)));
my ($uncompressed, $lengths) = VLR_encoding(string2symbols($bwt));
print $out_fh pack('N', $idx);
print $out_fh mrl_compress_symbolic($uncompressed, \&lzss_compress_symbolic);
print $out_fh create_huffman_entry(rle4_encode($lengths));
}
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $idx = unpack('N', join('', map { getc($fh) // die "decompression error" } 1 .. 4));
my $uncompressed = mrl_decompress_symbolic($fh, \&lzss_decompress_symbolic);
my $lengths = rle4_decode(decode_huffman_entry($fh));
my $dec = VLR_decoding($uncompressed, $lengths);
print $out_fh symbols2string(rle4_decode(bwt_decode($dec, $idx)));
}
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwt2_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 14 June 2023
# Edit: 19 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-To-Front transform (MTF) + Run-length encoding (RLE) + Bzip2.
# Reference:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWT2',
VERSION => '0.01',
FORMAT => 'bwt2',
CHUNK_SIZE => 1 << 17,
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
print $out_fh bwt_compress($chunk, sub ($s) { lzss_compress_symbolic($s, \&mrl_compress_symbolic) });
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
print $out_fh bwt_decompress($fh, sub ($s) { lzss_decompress_symbolic($s, \&mrl_decompress_symbolic) });
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bwt_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 14 June 2023
# Edit: 21 March 2024
# https://github.com/trizen
# Compress/decompress files using Burrows-Wheeler Transform (BWT) + Move-to-Front Transform + Run-length encoding + Huffman coding.
# Reference:
# Data Compression (Summer 2023) - Lecture 13 - BZip2
# https://youtube.com/watch?v=cvoZbBZ3M2A
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'BWT',
VERSION => '0.02',
FORMAT => 'bwt',
CHUNK_SIZE => 1 << 17,
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(2);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
print $out_fh bwt_compress($chunk);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
print $out_fh bwt_decompress($fh);
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/bzip2_file_compression.pl
================================================
#!/usr/bin/perl
# Compress files using Bzip2.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use IO::Compress::Bzip2 qw(bzip2);
use IO::Uncompress::Bunzip2 qw(bunzip2);
use constant {
PKGNAME => 'BZIP2',
VERSION => '0.01',
FORMAT => 'bz2',
};
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Compress data
bzip2($fh, $out_fh) or die "compression error";
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
bunzip2($fh, $out_fh) or die "decompression error";
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/gzip_file_compression.pl
================================================
#!/usr/bin/perl
# Compress files using Gzip.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use IO::Compress::Gzip qw(gzip);
use IO::Uncompress::Gunzip qw(gunzip);
use constant {
PKGNAME => 'GZIP',
VERSION => '0.01',
FORMAT => 'gz',
};
sub usage ($code = 0) {
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Compress data
gzip($fh, $out_fh) or die "compression error";
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
gunzip($fh, $out_fh) or die "decompression error";
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/hblz_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 17 June 2023
# Edit: 31 July 2024
# https://github.com/trizen
# Compress/decompress files using Huffman coding, followed by LZ77 compression (LZ4-like) on bits + Bzip2 on the literals.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'HBLZ',
VERSION => '0.01',
FORMAT => 'hblz',
CHUNK_SIZE => 1 << 18, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
($output = basename($input)) =~ s{$ext}{}
|| die "$0: no output file specified!\n";
}
if (not $opt{r} and -e $output) {
print "'$output' already exists! -- Replace? [y/N] ";
<STDIN> =~ /^y/i || exit 17;
}
decompress_file($input, $output)
|| die "$0: error: decompression failed!\n";
}
elsif ($input !~ $ext || (defined($output) && $output =~ $ext)) {
$output //= basename($input) . '.' . FORMAT;
compress_file($input, $output)
|| die "$0: error: compression failed!\n";
}
else {
warn "$0: don't know what to do...\n";
usage(1);
}
}
# Compress file
sub compress_file ($input, $output) {
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
my $header = SIGNATURE;
# Open the output file for writing
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for write: $!";
# Print the header
print $out_fh $header;
# Compress data
while (read($fh, (my $chunk), CHUNK_SIZE)) {
my $bits = unpack('B*', create_huffman_entry(string2symbols($chunk)));
my ($uncompressed, $distances, $lengths, $matches) = do {
local $Compression::Util::LZ_MIN_LEN = 8 * 4; # minimum match length
local $Compression::Util::LZ_MAX_LEN = 1 << 15; # maximum match length
local $Compression::Util::LZ_MAX_CHAIN_LEN = 64; # higher value = better compression
lz77_encode($bits);
};
my $ubits = pack('C*', @$uncompressed);
my $rem = length($ubits) % 8;
my $str = pack('B*', $ubits);
print $out_fh chr($rem);
print $out_fh mrl_compress_symbolic($str, \&lzss_compress_symbolic);
print $out_fh create_huffman_entry($lengths);
print $out_fh create_huffman_entry($matches);
print $out_fh obh_encode($distances, \&mrl_compress_symbolic);
}
# Close the file
close $out_fh;
}
# Decompress file
sub decompress_file ($input, $output) {
# Open and validate the input file
open my $fh, '<:raw', $input
or die "Can't open file <<$input>> for reading: $!";
valid_archive($fh) || die "$0: file `$input' is not a \U${\FORMAT}\E v${\VERSION} archive!\n";
# Open the output file
open my $out_fh, '>:raw', $output
or die "Can't open file <<$output>> for writing: $!";
while (!eof($fh)) {
my $rem = ord getc $fh;
my $str = symbols2string(mrl_decompress_symbolic($fh, \&lzss_decompress_symbolic));
my $ubits = unpack('B*', $str);
if ($rem != 0) {
$ubits = substr($ubits, 0, -(8 - $rem));
}
my $uncompressed = [unpack('C*', $ubits)];
my $lengths = decode_huffman_entry($fh);
my $matches = decode_huffman_entry($fh);
my $distances = obh_decode($fh, \&mrl_decompress_symbolic);
my $bits = lz77_decode($uncompressed, $distances, $lengths, $matches);
print $out_fh symbols2string(decode_huffman_entry(pack('B*', $bits)));
}
# Close the file
close $fh;
close $out_fh;
}
main();
exit(0);
================================================
FILE: Compression/High-level/lz255_file_compression.pl
================================================
#!/usr/bin/perl
# Author: Trizen
# Date: 15 December 2022
# Edit: 01 September 2024
# https://github.com/trizen
# Compress/decompress files using LZSS compression + MRL + Huffman coding, using a maximum match distance of 255.
use 5.036;
use Getopt::Std qw(getopts);
use File::Basename qw(basename);
use Compression::Util qw(:all);
use constant {
PKGNAME => 'LZ255',
VERSION => '0.01',
FORMAT => 'lz255',
CHUNK_SIZE => 1 << 18, # higher value = better compression
};
# Container signature
use constant SIGNATURE => uc(FORMAT) . chr(1);
sub usage {
my ($code) = @_;
print <<"EOH";
usage: $0 [options] [input file] [output file]
options:
-e : extract
-i <filename> : input filename
-o <filename> : output filename
-r : rewrite output
-v : version number
-h : this message
examples:
$0 document.txt
$0 document.txt archive.${\FORMAT}
$0 archive.${\FORMAT} document.txt
$0 -e -i archive.${\FORMAT} -o document.txt
EOH
exit($code // 0);
}
sub version {
printf("%s %s\n", PKGNAME, VERSION);
exit;
}
sub valid_archive {
my ($fh) = @_;
if (read($fh, (my $sig), length(SIGNATURE), 0) == length(SIGNATURE)) {
$sig eq SIGNATURE || return;
}
return 1;
}
sub main {
my %opt;
getopts('ei:o:vhr', \%opt);
$opt{h} && usage(0);
$opt{v} && version();
my ($input, $output) = @ARGV;
$input //= $opt{i} // usage(2);
$output //= $opt{o};
my $ext = qr{\.${\FORMAT}\z}io;
if ($opt{e} || $input =~ $ext) {
if (not defined $output) {
gitextract_4x__q3zn/ ├── .gitignore ├── Analyzers/ │ ├── char_counter.pl │ ├── chr_freq.pl │ ├── dieharder.pl │ ├── first_letter_top.pl │ ├── kcal/ │ │ ├── kcal.pl │ │ └── products.csv │ ├── kernel_config_diff.pl │ ├── perl_code_analyzer.pl │ ├── perl_code_spellcheck.pl │ ├── reptop.pl │ ├── text_stats.pl │ ├── unidecode_word_top.pl │ ├── wcer.pl │ └── word_suffix_top.pl ├── Audio/ │ ├── auto-mp3tags.pl │ ├── group_audio_files.pl │ ├── mkv_audio_to_opus.pl │ ├── recompress_audio_track.pl │ ├── rem-mp3tags.pl │ ├── wave-cmp.pl │ └── wave-cmp2.pl ├── Benchmarks/ │ ├── array_range_vs_shift.pl │ ├── compression_algorithms.pl │ ├── json_vs_storable.pl │ ├── schwartzian_transform.pl │ └── types_of_variables.pl ├── Book tools/ │ ├── rosettacode_to_markdown.pl │ └── update_summary.pl ├── Compression/ │ ├── High-level/ │ │ ├── ablz_file_compression.pl │ │ ├── bbwr_file_compression.pl │ │ ├── blzss2_file_compression.pl │ │ ├── blzss_file_compression.pl │ │ ├── brlzss_file_compression.pl │ │ ├── bwac_file_compression.pl │ │ ├── bwad_file_compression.pl │ │ ├── bwlz2_file_compression.pl │ │ ├── bwlz3_file_compression.pl │ │ ├── bwlz_file_compression.pl │ │ ├── bwlza2_file_compression.pl │ │ ├── bwlza_file_compression.pl │ │ ├── bwlzad2_file_compression.pl │ │ ├── bwlzad_file_compression.pl │ │ ├── bwlzb_file_compression.pl │ │ ├── bwlzhd2_file_compression.pl │ │ ├── bwlzhd_file_compression.pl │ │ ├── bwlzss_file_compression.pl │ │ ├── bwrl2_file_compression.pl │ │ ├── bwrm2_file_compression.pl │ │ ├── bwrm_file_compression.pl │ │ ├── bwt2_file_compression.pl │ │ ├── bwt_file_compression.pl │ │ ├── bzip2_file_compression.pl │ │ ├── gzip_file_compression.pl │ │ ├── hblz_file_compression.pl │ │ ├── lz255_file_compression.pl │ │ ├── lz2ss_file_compression.pl │ │ ├── lz4_file_compression.pl │ │ ├── lz772_file_compression.pl │ │ ├── lz77_file_compression.pl │ │ ├── lz77f_file_compression.pl │ │ ├── lzac_file_compression.pl │ │ ├── lzb_file_compression.pl │ │ ├── lzbbw_file_compression.pl │ │ ├── lzbf_file_compression.pl │ │ ├── lzbh_file_compression.pl │ │ ├── lzbw2_file_compression.pl │ │ ├── lzbw3_file_compression.pl │ │ ├── lzbw4_file_compression.pl │ │ ├── lzbw5_file_compression.pl │ │ ├── lzbw_file_compression.pl │ │ ├── lzbwa_file_compression.pl │ │ ├── lzbwad_file_compression.pl │ │ ├── lzbwd_file_compression.pl │ │ ├── lzbwh_file_compression.pl │ │ ├── lzbws_file_compression.pl │ │ ├── lzhd2_file_compression.pl │ │ ├── lzhd_file_compression.pl │ │ ├── lzih_file_compression.pl │ │ ├── lzmrl2_file_compression.pl │ │ ├── lzmrl_file_compression.pl │ │ ├── lzop_file_compression.pl │ │ ├── lzsbw_file_compression.pl │ │ ├── lzss2_file_compression.pl │ │ ├── lzss77_file_compression.pl │ │ ├── lzss_file_compression.pl │ │ ├── lzssf_file_compression.pl │ │ ├── lzssm_file_compression.pl │ │ ├── lzw_file_compression.pl │ │ ├── mblz_file_compression.pl │ │ ├── mbwr_file_compression.pl │ │ ├── mrl_file_compression.pl │ │ ├── mybzip2_file_compression.pl │ │ ├── mygzip_file_compression.pl │ │ ├── mygzipf_file_compression.pl │ │ ├── mylz4_file_compression.pl │ │ ├── mylz4f_file_compression.pl │ │ ├── myzlib_file_compression.pl │ │ ├── rablz_file_compression.pl │ │ ├── rlzss_file_compression.pl │ │ ├── sbwt_file_compression.pl │ │ ├── xz_file_compression.pl │ │ ├── zlib_file_compression.pl │ │ └── zstd_file_compression.pl │ ├── bbwr_file_compression.pl │ ├── bqof_file_compression.pl │ ├── bwac_file_compression.pl │ ├── bwad_file_compression.pl │ ├── bwaz_file_compression.pl │ ├── bwlz2_file_compression.pl │ ├── bwlz_file_compression.pl │ ├── bwlza2_file_compression.pl │ ├── bwlza_file_compression.pl │ ├── bwlzad2_file_compression.pl │ ├── bwlzad_file_compression.pl │ ├── bwlzhd_file_compression.pl │ ├── bwlzss_file_compression.pl │ ├── bwrl2_file_compression.pl │ ├── bwrl_file_compression.pl │ ├── bwrla_file_compression.pl │ ├── bwrlz2_file_compression.pl │ ├── bwrlz_file_compression.pl │ ├── bwrm_file_compression.pl │ ├── bwt2_file_compression.pl │ ├── bwt_file_compression.pl │ ├── bww_file_compression.pl │ ├── bzip2_compressor.pl │ ├── bzip2_decompressor.pl │ ├── bzip2_file_compression.pl │ ├── compress.pl │ ├── gzip2_file_compression.pl │ ├── gzip_block_type_1.pl │ ├── gzip_block_type_1_huffman_only.pl │ ├── gzip_block_type_2.pl │ ├── gzip_block_type_2_huffman_only.pl │ ├── gzip_block_type_2_simple.pl │ ├── gzip_comment.pl │ ├── gzip_decompressor.pl │ ├── gzip_file_compression.pl │ ├── gzip_store.pl │ ├── hfm_file_compression.pl │ ├── lz4_compressor.pl │ ├── lz4_decompressor.pl │ ├── lz4_file_compression.pl │ ├── lz77_file_compression.pl │ ├── lza_file_compression.pl │ ├── lzac_file_compression.pl │ ├── lzaz_file_compression.pl │ ├── lzb2_file_compression.pl │ ├── lzb_file_compression.pl │ ├── lzbf2_file_compression.pl │ ├── lzbf_file_compression.pl │ ├── lzbh_file_compression.pl │ ├── lzbw_file_compression.pl │ ├── lzbwa_file_compression.pl │ ├── lzbwad_file_compression.pl │ ├── lzbwd_file_compression.pl │ ├── lzbwh_file_compression.pl │ ├── lzh_file_compression.pl │ ├── lzhc_file_compression.pl │ ├── lzhd_file_compression.pl │ ├── lzih_file_compression.pl │ ├── lzsa_file_compression.pl │ ├── lzsad_file_compression.pl │ ├── lzsbw_file_compression.pl │ ├── lzss2_file_compression.pl │ ├── lzss_file_compression.pl │ ├── lzssf_file_compression.pl │ ├── lzsst2_file_compression.pl │ ├── lzsst_file_compression.pl │ ├── lzt2_file_compression.pl │ ├── lzt_file_compression.pl │ ├── lzw_file_compression.pl │ ├── mbwr_file_compression.pl │ ├── mra_file_compression.pl │ ├── mrh_file_compression.pl │ ├── mrlz_file_compression.pl │ ├── ppmh_file_compression.pl │ ├── qof_file_compression.pl │ ├── rans_file_compression.pl │ ├── rlac_file_compression.pl │ ├── rlh_file_compression.pl │ ├── tac_file_compression.pl │ ├── tacc_file_compression.pl │ ├── test_compressors.pl │ ├── tzip2_file_compression.pl │ ├── tzip_file_compression.pl │ ├── unzip.pl │ ├── zip.pl │ ├── zlib_compressor.pl │ ├── zlib_decompressor.pl │ └── zlib_file_compression.pl ├── Converters/ │ ├── another_notes_to_markdown.pl │ ├── another_notes_to_material_notes.pl │ ├── any_to_3gp.pl │ ├── ass2srt.pl │ ├── code2pdf.pl │ ├── euler2pdf.pl │ ├── from_hex.pl │ ├── gdbm_to_berkeley.pl │ ├── gitbook2pdf.pl │ ├── gz2xz.pl │ ├── html2pdf.pl │ ├── html2pdf_chromium.pl │ ├── html2text.pl │ ├── json2csv.pl │ ├── markdown2pdf.pl │ ├── markdown2pdf_chromium.pl │ ├── markdown2text.pl │ ├── notepadfree_to_txt.pl │ ├── pod2pdf.pl │ ├── pod2text.pl │ ├── recompress.pl │ ├── unicode2ascii.pl │ ├── vnt2txt_simple.pl │ ├── xml2hash.pl │ ├── xpm_c_to_perl.pl │ ├── xz2gz.pl │ ├── zip2tar.pl │ └── zip2tar_fast.pl ├── Decoders/ │ ├── base64_decoding-tutorial.pl │ ├── cnp_info.pl │ └── named_parameters.pl ├── Digest/ │ ├── brute-force_resistant_hashing.pl │ └── crc32.pl ├── Encoding/ │ ├── adaptive_huffman_coding.pl │ ├── arithmetic_coding.pl │ ├── arithmetic_coding_adaptive_contexts_in_fixed_bits.pl │ ├── arithmetic_coding_adaptive_in_fixed_bits.pl │ ├── arithmetic_coding_anynum.pl │ ├── arithmetic_coding_in_fixed_bits.pl │ ├── arithmetic_coding_mpz.pl │ ├── ascii_encode_decode.pl │ ├── binary_arithmetic_coding.pl │ ├── binary_arithmetic_coding_anynum.pl │ ├── binary_variable_length_run_encoding.pl │ ├── binradix_arithmetic_coding.pl │ ├── binradix_arithmetic_coding_anynum.pl │ ├── burrows-wheeler_file_transform.pl │ ├── burrows-wheeler_transform-n-char_generalization.pl │ ├── burrows-wheeler_transform.pl │ ├── burrows-wheeler_transform_symbolic.pl │ ├── delta_encoding_with_double-elias_coding.pl │ ├── delta_encoding_with_elias_coding.pl │ ├── delta_encoding_with_unary_coding.pl │ ├── delta_rle_elias_encoding.pl │ ├── double-elias_gamma_encoding.pl │ ├── elias_gamma_encoding.pl │ ├── eyes_dropper.pl │ ├── fibonacci_coding.pl │ ├── huffman_coding.pl │ ├── int2bytes.pl │ ├── integers_binary_encoding.pl │ ├── integers_binary_encoding_with_delta_coding.pl │ ├── integers_binary_encoding_with_huffman_coding.pl │ ├── jpeg_transform.pl │ ├── length_encoder.pl │ ├── lz77_encoding.pl │ ├── lz77_encoding_symbolic.pl │ ├── lzss_encoding.pl │ ├── lzss_encoding_hash_table.pl │ ├── lzss_encoding_hash_table_fast.pl │ ├── lzss_encoding_symbolic.pl │ ├── lzt-fast.pl │ ├── lzw_encoding.pl │ ├── math_expr_encoder.pl │ ├── move-to-front_transform.pl │ ├── mtf-delta_encoding.pl │ ├── png_transform.pl │ ├── ppm_encoding.pl │ ├── ppm_encoding_dynamic.pl │ ├── rANS_encoding.pl │ ├── rANS_encoding_mpz.pl │ ├── run_length_with_elias_coding.pl │ ├── string_to_integer_encoding_based_on_primes.pl │ ├── swap_transform.pl │ ├── tlen_encoding.pl │ └── variable_length_run_encoding.pl ├── Encryption/ │ ├── RSA_encryption.pl │ ├── age-lf.pl │ ├── backdoored_rsa_with_x25519.pl │ ├── cbc+xor_file_encrypter.pl │ ├── crypt_rsa.pl │ ├── one-time_pad.pl │ ├── plage.pl │ └── simple_XOR_cipher.pl ├── File Readers/ │ ├── ldump │ ├── multi-file-line-reader.pl │ ├── n_repeated_lines.pl │ └── tailz ├── File Workers/ │ ├── arxiv_pdf_renamer.pl │ ├── auto_extensions.pl │ ├── collect_gifs.pl │ ├── collect_videos.pl │ ├── delete_if_exists.pl │ ├── dir_file_updater.pl │ ├── file-mover.pl │ ├── file_updater.pl │ ├── filename_cmp_del.pl │ ├── keep_this_formats.pl │ ├── make_filenames_portable.pl │ ├── md5_rename.pl │ ├── multiple_backups.pl │ ├── remove_eof_newlines.pl │ ├── split_to_n_lines.pl │ ├── sub_renamer.pl │ ├── timestamp_rename.pl │ ├── undir.pl │ └── unidec_renamer.pl ├── Finders/ │ ├── ampath │ ├── dup_subtr_finder.pl │ ├── fcheck.pl │ ├── fdf │ ├── fdf-attr │ ├── fdf-filename │ ├── file_binsearch.pl │ ├── find_perl_scripts.pl │ ├── find_similar_filenames.pl │ ├── find_similar_filenames_unidec.pl │ ├── fsf.pl │ ├── fsfn.pl │ ├── human-like_finder.pl │ ├── large_file_search.pl │ ├── locatepm │ ├── longest_substring.pl │ ├── mimefind.pl │ ├── model_matching_system.pl │ ├── path_diff.pl │ ├── plocate.pl │ └── similar_files_levenshtein.pl ├── Formatters/ │ ├── ascii_table_csv.pl │ ├── file_columner.pl │ ├── fstab_beautifier.pl │ ├── js_beautify │ ├── reformat_literal_perl_strings.pl │ ├── replace_html_links.pl │ ├── sort_perl_subroutines.pl │ └── word_columner.pl ├── GD/ │ ├── AND_sierpinski_triangle.pl │ ├── LSystem/ │ │ ├── LSystem.pm │ │ ├── Turtle.pm │ │ ├── honeycomb.pl │ │ ├── honeycomb_2.pl │ │ ├── plant.pl │ │ ├── plant_2.pl │ │ ├── plant_3.pl │ │ ├── sierpinski_triangle.pl │ │ └── tree.pl │ ├── XOR_pattern.pl │ ├── abstract_map.pl │ ├── barnsley_fern_fractal.pl │ ├── binary_triangle.pl │ ├── black_star_turtle.pl │ ├── black_yellow_number_triangles.pl │ ├── box_pattern.pl │ ├── chaos_game_pentagon.pl │ ├── chaos_game_tetrahedron.pl │ ├── chaos_game_triangle.pl │ ├── circular_prime_triangle.pl │ ├── circular_triangle.pl │ ├── collatz_triangle.pl │ ├── color_wheel.pl │ ├── complex_square.pl │ ├── congruence_of_squares_triangle.pl │ ├── cuboid_turtle.pl │ ├── cuboid_turtle3.pl │ ├── cuboid_turtle_2.pl │ ├── dancing_shapes.pl │ ├── divisor_circles.pl │ ├── divisor_triangle.pl │ ├── elementary_cellular_automaton_generalized.pl │ ├── fact_exp_primorial_growing.pl │ ├── factor_circles.pl │ ├── factor_triangle.pl │ ├── factorial_turtles.pl │ ├── factors_of_two_triangle.pl │ ├── farey_turnings_plot.pl │ ├── fgraph.pl │ ├── fgraph_precision.pl │ ├── fibonacci_gd.pl │ ├── fibonacci_spirals.pl │ ├── generator_turtle.pl │ ├── geometric_shapes.pl │ ├── goldbach_conjecture_possibilities.pl │ ├── horsie_art.pl │ ├── julia_set.pl │ ├── julia_set_complex.pl │ ├── julia_set_random.pl │ ├── julia_set_rperl.pl │ ├── koch_snowflakes.pl │ ├── langton_s_ant_gd.pl │ ├── line_pattern_triangles.pl │ ├── magic_triangle.pl │ ├── mandelbrot_like_set.pl │ ├── mandelbrot_like_set_gcomplex.pl │ ├── mathematical_butt.pl │ ├── mathematical_shapes.pl │ ├── mirror_shells.pl │ ├── moebius_walking_line.pl │ ├── number_triangles.pl │ ├── numeric_circles.pl │ ├── pascal-fibonacci_triangle.pl │ ├── pascal_powers_of_two_triangle.pl │ ├── pascal_s_triangle_multiples.pl │ ├── pascal_special_triangle.pl │ ├── pattern_triangle.pl │ ├── peacock_triangles.pl │ ├── pi_abstract_art.pl │ ├── pi_turtle.pl │ ├── prime_consecutive_sums.pl │ ├── prime_gaps.pl │ ├── prime_rectangles.pl │ ├── prime_stripe_triangle.pl │ ├── prime_triangle_90deg.pl │ ├── pythagoras_tree.pl │ ├── random_abstract_art.pl │ ├── random_abstract_art_2.pl │ ├── random_langton_s_ant.pl │ ├── random_looking_pattern_triangle.pl │ ├── random_machinery_art.pl │ ├── random_noise_triangle.pl │ ├── random_turtles.pl │ ├── real_shell.pl │ ├── recursive_squares.pl │ ├── regular_poligons.pl │ ├── reversed_prime_triangles.pl │ ├── right_triangle_primes.pl │ ├── sandpiles.pl │ ├── sierpinski_fibonacci_triangle.pl │ ├── sierpinski_triangle.pl │ ├── spinning_shapes.pl │ ├── spiral_matrix_primes.pl │ ├── spiral_tree.pl │ ├── square_of_circles.pl │ ├── star_turtle.pl │ ├── stern_brocot_shapes.pl │ ├── triangle_factors.pl │ ├── triangle_primes.pl │ ├── triangle_primes_2.pl │ ├── triangle_primes_irregular.pl │ ├── trizen_fan_turtle.pl │ ├── trizen_flat_logo.pl │ ├── trizen_new_logo.pl │ ├── trizen_old_logo.pl │ ├── trizen_text_art.pl │ ├── tupper_s_self-referential_formula.pl │ ├── wavy_triangle.pl │ ├── zeta_real_half_terms.pl │ └── zig-zag_primes.pl ├── GTK+/ │ ├── mouse_position.pl │ └── tray-file-browser.pl ├── Game solvers/ │ ├── asciiplanes-player-v2.pl │ ├── asciiplanes-player.pl │ ├── dice_game_solver.pl │ ├── peg-solitaire-solver │ ├── reaction_time_test.pl │ ├── reflex_sheep_game.pl │ ├── sudoku_dice_game_solver.pl │ ├── sudoku_generator.pl │ ├── sudoku_solver.pl │ ├── sudoku_solver_backtracking.pl │ ├── sudoku_solver_iterative.pl │ ├── sudoku_solver_stack.pl │ └── visual_memory_test.pl ├── Games/ │ ├── arrow-key_drawer.pl │ ├── asciiplanes │ └── snake_game.pl ├── Generators/ │ ├── bernoulli_numbers_formulas.pl │ ├── faulhaber_s_formula_symbolic.pl │ ├── faulhaber_s_formulas_expanded.pl │ ├── faulhaber_s_formulas_expanded_2.pl │ ├── faulhaber_s_formulas_generator.pl │ ├── parsing_and_code_gen.pl │ ├── powers_of_factorial.pl │ ├── random_lsystem_generator.pl │ ├── semiprime_equationization_C_generator.pl │ ├── semiprime_equationization_Perl_generator.pl │ └── zeta_2n_generator.pl ├── Greppers/ │ ├── marif │ ├── mime_types.pl │ ├── mp3grep.pl │ ├── scgrep │ └── unigrep.pl ├── HAL/ │ ├── HAL3736/ │ │ ├── HAL3736.memory │ │ └── HAL3736.pl │ ├── HAL8212/ │ │ ├── HAL8212.memory │ │ └── HAL8212.pl │ └── HAL9000/ │ ├── HAL9000.memory │ └── HAL9000.pl ├── Image/ │ ├── 2x_zoom.pl │ ├── add_exif_info.pl │ ├── bitmap_monochrome_encoding_decoding.pl │ ├── bwt_horizontal_transform.pl │ ├── bwt_rgb_horizontal_transform.pl │ ├── bwt_rgb_vertical_transform.pl │ ├── bwt_vertical_transform.pl │ ├── collage.pl │ ├── complex_transform.pl │ ├── cyan_vision.pl │ ├── darken_image.pl │ ├── diff_negative.pl │ ├── edge_detector.pl │ ├── extract_jpegs.pl │ ├── fractal_frame.pl │ ├── fractal_frame_transparent.pl │ ├── gd_png2jpg.pl │ ├── gd_similar_images.pl │ ├── gd_star_trails.pl │ ├── gif2webp.pl │ ├── horizontal_scrambler.pl │ ├── image-hard-rotate.pl │ ├── image-unpack.pl │ ├── image2ascii.pl │ ├── image2audio.pl │ ├── image2digits.pl │ ├── image2html.pl │ ├── image2matrix.pl │ ├── image2mozaic.pl │ ├── image2png.pl │ ├── image2prime.pl │ ├── image_metadata_clone.pl │ ├── imager_similar_images.pl │ ├── img-autocrop-avg.pl │ ├── img-autocrop-whitebg.pl │ ├── img-autocrop.pl │ ├── img_composition.pl │ ├── img_rewrite.pl │ ├── julia_transform.pl │ ├── lookalike_images.pl │ ├── magick_png2jpg.pl │ ├── magick_similar_images.pl │ ├── magick_star_trails.pl │ ├── matrix_visual.pl │ ├── mirror_images.pl │ ├── mtf_horizontal_transform.pl │ ├── mtf_vertical_transform.pl │ ├── nearest_neighbor_interpolation.pl │ ├── optimize_images.pl │ ├── optimize_images_littleutils.pl │ ├── outguess-png-imager.pl │ ├── outguess-png.pl │ ├── photo_mosaic_from_images.pl │ ├── qhi_decoder.pl │ ├── qhi_encoder.pl │ ├── qoi_decoder.pl │ ├── qoi_encoder.pl │ ├── qzst_decoder.pl │ ├── qzst_encoder.pl │ ├── recompress_images.pl │ ├── remove_sensitive_exif_tags.pl │ ├── resize_images.pl │ ├── rgb_dump.pl │ ├── sharp_2x_zoom.pl │ ├── slideshow.pl │ ├── vertical_scrambler.pl │ ├── visualize_binary.pl │ ├── webp2png.pl │ ├── zuper_image_decoder.pl │ └── zuper_image_encoder.pl ├── JAPH/ │ ├── alien_japh.pl │ ├── alpha_ascii_japh.pl │ ├── alpha_japh.pl │ ├── alpha_japh_2.pl │ ├── alpha_japh_3.pl │ ├── arrow_japh.pl │ ├── barewords_japh.pl │ ├── cubic_japh.pl │ ├── invisible_japh.pl │ ├── japh_from_ambiguity.pl │ ├── japh_from_auto-quoted_keywords.pl │ ├── japh_from_escapes.pl │ ├── japh_from_escapes_2.pl │ ├── japh_from_eval_subst.pl │ ├── japh_from_keywords.pl │ ├── japh_from_pod.pl │ ├── japh_from_poetry.pl │ ├── japh_from_punctuation_chars.pl │ ├── japh_from_subs.pl │ ├── japh_from_the_deep.pl │ ├── japh_variable.pl │ ├── japh_variables.pl │ ├── japh_variables_2.pl │ ├── leet_japh.pl │ ├── length_obfuscation.pl │ ├── log_japh.pl │ ├── log_japh_2.pl │ ├── non-alphanumeric_japh.pl │ ├── re_eval_japh.pl │ ├── slash_r_japh.pl │ ├── ternary_japh.pl │ ├── up_and_down.pl │ ├── vec_japh.pl │ └── vec_japh_2.pl ├── LICENSE ├── Lingua/ │ ├── en_phoneme.pl │ ├── lingua_ro_numbers.pl │ ├── poetry_from_poetry.pl │ ├── poetry_from_poetry_with_variations.pl │ ├── random_poetry_generator.pl │ └── rus_translit.pl ├── Math/ │ ├── 1_over_n_is_finite.pl │ ├── 1_over_n_period_length.pl │ ├── BPSW_primality_test.pl │ ├── BPSW_primality_test_mpz.pl │ ├── LUP_decomposition.pl │ ├── MBE_factorization_method.pl │ ├── PSW_primality_test.pl │ ├── PSW_primality_test_mpz.pl │ ├── RSA_PRNG.pl │ ├── RSA_example.pl │ ├── additive_binomial.pl │ ├── additive_partitions.pl │ ├── alexandrian_integers.pl │ ├── almost_prime_divisors.pl │ ├── almost_prime_divisors_recursive.pl │ ├── almost_prime_numbers.pl │ ├── almost_prime_numbers_in_range.pl │ ├── almost_prime_numbers_in_range_mpz.pl │ ├── almost_prime_numbers_in_range_v2.pl │ ├── almost_primes_from_factor_list.pl │ ├── almost_primes_in_range_from_factor_list.pl │ ├── area_of_triangle.pl │ ├── arithmetic_derivative.pl │ ├── arithmetic_expressions.pl │ ├── arithmetic_geometric_mean_complex.pl │ ├── arithmetic_sum_closed_form.pl │ ├── ascii_cuboid.pl │ ├── ascii_julia_set.pl │ ├── ascii_mandelbrot_set.pl │ ├── batir_factorial_asymptotic_formula_mpfr.pl │ ├── bell_numbers.pl │ ├── bell_numbers_mpz.pl │ ├── bernoulli_denominators.pl │ ├── bernoulli_denominators_records.pl │ ├── bernoulli_numbers.pl │ ├── bernoulli_numbers_from_factorials.pl │ ├── bernoulli_numbers_from_factorials_mpq.pl │ ├── bernoulli_numbers_from_factorials_mpz.pl │ ├── bernoulli_numbers_from_factorials_visual.pl │ ├── bernoulli_numbers_from_primes.pl │ ├── bernoulli_numbers_from_primes_gmpf.pl │ ├── bernoulli_numbers_from_primes_mpfr.pl │ ├── bernoulli_numbers_from_primes_ntheory.pl │ ├── bernoulli_numbers_from_tangent_numbers.pl │ ├── bernoulli_numbers_from_zeta.pl │ ├── bernoulli_numbers_ramanujan_congruences.pl │ ├── bernoulli_numbers_ramanujan_congruences_unreduced.pl │ ├── bernoulli_numbers_recursive.pl │ ├── bernoulli_numbers_recursive_2.pl │ ├── bernoulli_numbers_seidel.pl │ ├── bi-unitary_divisors.pl │ ├── binary_gcd_algorithm.pl │ ├── binary_gcd_algorithm_mpz.pl │ ├── binary_multiplier.pl │ ├── binary_prime_encoder.pl │ ├── binary_prime_encoder_fast.pl │ ├── binary_prime_sieve_mpz.pl │ ├── binary_splitting_product.pl │ ├── binomial_sum_with_imaginary_term.pl │ ├── binomial_theorem.pl │ ├── bitstring_prime_sieve_mpz.pl │ ├── bitstring_prime_sieve_vec.pl │ ├── both_truncatable_primes_in_base.pl │ ├── brazilian_primes_constant.pl │ ├── brown_numbers.pl │ ├── carmichael_factorization_method.pl │ ├── carmichael_factorization_method_generalized.pl │ ├── carmichael_numbers_from_multiple.pl │ ├── carmichael_numbers_from_multiple_mpz.pl │ ├── carmichael_numbers_from_multiple_recursive_mpz.pl │ ├── carmichael_numbers_generation_erdos_method.pl │ ├── carmichael_numbers_generation_erdos_method_dynamic_programming.pl │ ├── carmichael_numbers_in_range.pl │ ├── carmichael_numbers_in_range_from_prime_factors.pl │ ├── carmichael_numbers_in_range_mpz.pl │ ├── carmichael_numbers_random.pl │ ├── carmichael_strong_fermat_pseudoprimes_in_range.pl │ ├── carmichael_strong_fermat_pseudoprimes_in_range_mpz.pl │ ├── cartesian_product_iter.pl │ ├── cartesian_product_rec.pl │ ├── cauchy_numbers_of_first_type.pl │ ├── chebyshev_factorization_method.pl │ ├── chebyshev_factorization_method_mpz.pl │ ├── chernick-carmichael_numbers.pl │ ├── chernick-carmichael_numbers_below_limit.pl │ ├── chernick-carmichael_polynomials.pl │ ├── chernick-carmichael_with_n_factors_sieve.pl │ ├── chinese_factorization_method.pl │ ├── coin_change.pl │ ├── collatz_function.pl │ ├── complex_exponentiation_in_real_numbers.pl │ ├── complex_logarithm_in_real_numbers.pl │ ├── complex_modular_multiplicative_inverse.pl │ ├── complex_zeta_in_real_numbers.pl │ ├── congruence_of_powers_factorization_method.pl │ ├── consecutive_partitions.pl │ ├── continued_fraction_expansion_of_sqrt_of_n.pl │ ├── continued_fraction_expansion_of_sqrt_of_n_mpz.pl │ ├── continued_fraction_factorization_method.pl │ ├── continued_fractions.pl │ ├── continued_fractions_for_e.pl │ ├── continued_fractions_for_nth_roots.pl │ ├── continued_fractions_for_pi.pl │ ├── continued_fractions_for_square_roots.pl │ ├── continued_fractions_prime_constant.pl │ ├── convergent_series.pl │ ├── cosmic_calendar.pl │ ├── count_of_brilliant_numbers.pl │ ├── count_of_cube-full_numbers.pl │ ├── count_of_integers_with_gpf_of_n_equals_p.pl │ ├── count_of_integers_with_lpf_of_n_equals_p.pl │ ├── count_of_inverse_tau_in_range.pl │ ├── count_of_k-almost_primes.pl │ ├── count_of_k-omega_primes.pl │ ├── count_of_k-powerfree_numbers.pl │ ├── count_of_k-powerful_numbers.pl │ ├── count_of_k-powerful_numbers_in_range.pl │ ├── count_of_perfect_powers.pl │ ├── count_of_prime_power.pl │ ├── count_of_prime_signature_numbers.pl │ ├── count_of_rough_numbers.pl │ ├── count_of_rough_numbers_recursive.pl │ ├── count_of_smooth_numbers.pl │ ├── count_of_smooth_numbers_memoized.pl │ ├── count_of_smooth_numbers_mpz.pl │ ├── count_of_smooth_numbers_mpz_2.pl │ ├── count_of_smooth_numbers_with_k_factors.pl │ ├── count_of_squarefree_k-almost_primes.pl │ ├── count_of_squarefree_numbers.pl │ ├── count_subtriangles.pl │ ├── cube-full_numbers.pl │ ├── cuboid.pl │ ├── cyclotomic_factorization_method.pl │ ├── cyclotomic_factorization_method_2.pl │ ├── cyclotomic_polynomial.pl │ ├── definite_integral_numerical_approximation.pl │ ├── dickson_linear_forms_prime_sieve.pl │ ├── dickson_linear_forms_prime_sieve_in_range.pl │ ├── dickson_linear_forms_prime_sieve_in_range_2.pl │ ├── difference_of_k_powers.pl │ ├── difference_of_powers_factorization_method.pl │ ├── difference_of_three_squares_solutions.pl │ ├── difference_of_two_squares_solutions.pl │ ├── digits_to_number_subquadratic_algorithm.pl │ ├── digits_to_number_subquadratic_algorithm_mpz.pl │ ├── dirichlet_hyperbola_method.pl │ ├── discrete_logarithm_pollard_rho.pl │ ├── discrete_logarithm_pollard_rho_mpz.pl │ ├── discrete_root.pl │ ├── divisors_descending_lazy.pl │ ├── divisors_lazy.pl │ ├── divisors_lazy_fast.pl │ ├── divisors_less_than_k.pl │ ├── divisors_of_factorial_below_limit.pl │ ├── divisors_of_factorial_in_range_iterator.pl │ ├── dixon_factorization_method.pl │ ├── e_from_binomial.pl │ ├── e_primorial.pl │ ├── ecm_factorization_method.pl │ ├── elementary_cellular_automaton_generalized.pl │ ├── elliptic-curve_factorization_method.pl │ ├── elliptic-curve_factorization_method_with_B2_stage.pl │ ├── elliptic-curve_factorization_method_with_B2_stage_mpz.pl │ ├── equally_spaced_squares_solutions.pl │ ├── esthetic_numbers.pl │ ├── ethiopian_multiplication.pl │ ├── ethiopian_multiplication_binary.pl │ ├── even_fermat_pseudoprimes_in_range.pl │ ├── even_squarefree_fermat_pseudoprimes_in_range.pl │ ├── exponential_divisors.pl │ ├── factorial_difference_of_prime_squares.pl │ ├── factorial_dsc_algorithm.pl │ ├── factorial_expansion_of_reciprocals.pl │ ├── factorial_from_primes.pl │ ├── factorial_from_primes_simple.pl │ ├── factorial_from_primorials.pl │ ├── factorial_from_trinomial_coefficients.pl │ ├── factorial_in_half_steps.pl │ ├── factorions_in_base_n.pl │ ├── factorization_with_difference_of_prime_factors.pl │ ├── farey_rational_approximation.pl │ ├── faulhaber_s_formula.pl │ ├── fermat_factorization_method.pl │ ├── fermat_factorization_method_2.pl │ ├── fermat_frobenius_quadratic_primality_test.pl │ ├── fermat_overpseudoprimes_generation.pl │ ├── fermat_overpseudoprimes_in_range.pl │ ├── fermat_pseudoprimes_from_multiple.pl │ ├── fermat_pseudoprimes_from_multiple_mpz.pl │ ├── fermat_pseudoprimes_generation.pl │ ├── fermat_pseudoprimes_generation_2.pl │ ├── fermat_pseudoprimes_generation_3.pl │ ├── fermat_pseudoprimes_in_range.pl │ ├── fermat_pseudoprimes_in_range_mpz.pl │ ├── fermat_superpseudoprimes_generation.pl │ ├── fibonacci_closed_form.pl │ ├── fibonacci_closed_form_2.pl │ ├── fibonacci_encoding.pl │ ├── fibonacci_factorization_method.pl │ ├── fibonacci_k-th_order.pl │ ├── fibonacci_k-th_order_efficient_algorithm.pl │ ├── fibonacci_k-th_order_fast.pl │ ├── fibonacci_k-th_order_odd_primes_indices.pl │ ├── fibonacci_number_fast.pl │ ├── fibonacci_polynomials_closed_form.pl │ ├── fibonacci_pseudoprimes_generation.pl │ ├── find_least_common_denominator.pl │ ├── floor_and_ceil_functions_fourier_series.pl │ ├── flt_factorization_method.pl │ ├── fraction_approximation.pl │ ├── fraction_to_decimal_expansion.pl │ ├── fractional_pi.pl │ ├── frobenius_pseudoprimes_generation.pl │ ├── fubini_numbers.pl │ ├── fubini_numbers_2.pl │ ├── fubini_numbers_recursive.pl │ ├── function_graph.pl │ ├── function_inverse_binary_search.pl │ ├── gamma_function.pl │ ├── gaussian_divisors.pl │ ├── gaussian_factors.pl │ ├── gaussian_integers_sum.pl │ ├── general_binary_multiplier.pl │ ├── goldbach_conjecture_2n_prime.pl │ ├── goldbach_conjecture_increasing_primes.pl │ ├── goldbach_conjecture_possibilities.pl │ ├── goldbach_conjecture_random_primes.pl │ ├── golomb_s_sequence.pl │ ├── greatest_common_unitary_divisor.pl │ ├── hamming_numbers.pl │ ├── harmonic_numbers.pl │ ├── harmonic_numbers_from_digamma.pl │ ├── harmonic_numbers_from_powers.pl │ ├── harmonic_numbers_from_powers_mpz.pl │ ├── harmonic_prime_powers.pl │ ├── hybrid_prime_factorization.pl │ ├── infinitary_divisors.pl │ ├── inverse_of_bernoulli_numbers.pl │ ├── inverse_of_euler_totient.pl │ ├── inverse_of_factorial.pl │ ├── inverse_of_factorial_stirling.pl │ ├── inverse_of_fibonacci.pl │ ├── inverse_of_multiplicative_functions.pl │ ├── inverse_of_p_adic_valuation.pl │ ├── inverse_of_sigma_function.pl │ ├── inverse_of_sigma_function_fast.pl │ ├── inverse_of_sigma_function_generalized.pl │ ├── inverse_of_usigma_function.pl │ ├── inverse_tau_in_range.pl │ ├── invert_transform_of_factorials.pl │ ├── is_absolute_euler_pseudoprime.pl │ ├── is_almost_prime.pl │ ├── is_bfsw_pseudoprime.pl │ ├── is_chernick_carmichael_number.pl │ ├── is_even_perfect.pl │ ├── is_even_perfect_2.pl │ ├── is_even_perfect_3.pl │ ├── is_extra_bfsw_pseudoprime.pl │ ├── is_omega_prime.pl │ ├── is_perfect_power.pl │ ├── is_smooth_over_product.pl │ ├── is_squarefree_over_product.pl │ ├── is_sum_of_two_cubes.pl │ ├── is_sum_of_two_squares.pl │ ├── iterative_difference_of_central_divisors_to_reach_zero.pl │ ├── k-imperfect_numbers.pl │ ├── k-odd-powerful_numbers.pl │ ├── k-powerful_numbers.pl │ ├── k-powerful_numbers_in_range.pl │ ├── karatsuba_multiplication.pl │ ├── kempner_binomial_numbers.pl │ ├── klein_J_invariant_and_modular_lambda.pl │ ├── lambert_W_function.pl │ ├── lambert_W_function_complex.pl │ ├── lanczos_approximation.pl │ ├── least_k_such_that_k_times_k-th_prime_is_greater_than_10_to_the_n.pl │ ├── least_nonresidue.pl │ ├── legendary_question_six.pl │ ├── length_of_shortest_addition_chain.pl │ ├── lerch_zeta_function.pl │ ├── logarithmic_integral_asymptotic_formula.pl │ ├── logarithmic_root.pl │ ├── logarithmic_root_complex.pl │ ├── logarithmic_root_in_two_variables.pl │ ├── logarithmic_root_mpfr.pl │ ├── long_division.pl │ ├── long_multiplication.pl │ ├── lucas-carmichael_numbers_from_multiple.pl │ ├── lucas-carmichael_numbers_from_multiple_mpz.pl │ ├── lucas-carmichael_numbers_in_range.pl │ ├── lucas-carmichael_numbers_in_range_from_prime_factors.pl │ ├── lucas-carmichael_numbers_in_range_mpz.pl │ ├── lucas-miller_factorization_method.pl │ ├── lucas-pocklington_primality_proving.pl │ ├── lucas-pratt_primality_proving.pl │ ├── lucas-pratt_prime_records.pl │ ├── lucas_factorization_method.pl │ ├── lucas_factorization_method_generalized.pl │ ├── lucas_pseudoprimes_generation.pl │ ├── lucas_pseudoprimes_generation_erdos_method.pl │ ├── lucas_sequences_U_V.pl │ ├── lucas_sequences_U_V_mpz.pl │ ├── lucas_theorem.pl │ ├── magic_3-gon_ring.pl │ ├── magic_5-gon_ring.pl │ ├── map_num.pl │ ├── matrix_determinant_bareiss.pl │ ├── matrix_path_2-ways_best.pl │ ├── matrix_path_2-ways_greedy.pl │ ├── matrix_path_3-ways_best.pl │ ├── matrix_path_3-ways_diagonal_best.pl │ ├── matrix_path_3-ways_greedy.pl │ ├── matrix_path_4-ways_best.pl │ ├── matrix_path_4-ways_best_2.pl │ ├── matrix_path_4-ways_best_3.pl │ ├── matrix_path_4-ways_greedy.pl │ ├── maximum_product_of_parts_bisection.pl │ ├── maximum_square_remainder.pl │ ├── meissel_lehmer_prime_count.pl │ ├── mertens_function.pl │ ├── mertens_function_fast.pl │ ├── miller-rabin_deterministic_primality_test.pl │ ├── miller-rabin_deterministic_primality_test_mpz.pl │ ├── miller-rabin_factorization_method.pl │ ├── modular_bell_numbers.pl │ ├── modular_bell_numbers_mpz.pl │ ├── modular_binomial.pl │ ├── modular_binomial_fast.pl │ ├── modular_binomial_faster.pl │ ├── modular_binomial_faster_mpz.pl │ ├── modular_binomial_faster_mpz_2.pl │ ├── modular_binomial_ntheory.pl │ ├── modular_binomial_small_k.pl │ ├── modular_binomial_small_k_faster.pl │ ├── modular_cyclotomic_polynomial.pl │ ├── modular_factorial.pl │ ├── modular_factorial_crt.pl │ ├── modular_factorial_crt_mpz.pl │ ├── modular_fibonacci.pl │ ├── modular_fibonacci_anynum.pl │ ├── modular_fibonacci_cassini.pl │ ├── modular_fibonacci_cassini_fast.pl │ ├── modular_fibonacci_fast_mpz.pl │ ├── modular_fibonacci_mpz.pl │ ├── modular_fibonacci_polynomial.pl │ ├── modular_fibonacci_polynomial_2.pl │ ├── modular_hyperoperation.pl │ ├── modular_inverse.pl │ ├── modular_k-th_root_all_solutions.pl │ ├── modular_k-th_root_all_solutions_fast.pl │ ├── modular_k-th_root_all_solutions_fast_mpz.pl │ ├── modular_k-th_root_all_solutions_mpz.pl │ ├── modular_lucas_numbers.pl │ ├── modular_lucas_sequence_V.pl │ ├── modular_lucas_sequences_U_V.pl │ ├── modular_pseudo_square_root.pl │ ├── modular_pseudo_square_root_2.pl │ ├── modular_sigma_of_unitary_divisors_of_factorial.pl │ ├── modular_square_root.pl │ ├── modular_square_root_2.pl │ ├── modular_square_root_3.pl │ ├── modular_square_root_all_solutions.pl │ ├── modular_square_root_all_solutions_cipolla.pl │ ├── multi_sqrt_nums.pl │ ├── multinomial_coefficient.pl │ ├── multinomial_coefficient_from_binomial.pl │ ├── multiplicative_partitions.pl │ ├── multisets.pl │ ├── multivariate_gamma_function.pl │ ├── mysterious_sum-pentagonal_numbers.pl │ ├── mysterious_sum-pentagonal_numbers_2.pl │ ├── n_dimensional_circles.pl │ ├── near-power_factorization_method.pl │ ├── newton_s_method.pl │ ├── newton_s_method_recursive.pl │ ├── next_palindrome.pl │ ├── next_palindrome_from_non-palindrome.pl │ ├── next_palindrome_in_base.pl │ ├── next_power_of_two.pl │ ├── nth_composite.pl │ ├── nth_digit_of_fraction.pl │ ├── nth_prime_approx.pl │ ├── nth_root_good_rational_approximations.pl │ ├── nth_root_recurrence_constant.pl │ ├── nth_smooth_number.pl │ ├── number2expression.pl │ ├── number_of_conditional_GCDs.pl │ ├── number_of_connected_permutations.pl │ ├── number_of_partitions_into_2_distinct_positive_cubes.pl │ ├── number_of_partitions_into_2_distinct_positive_squares.pl │ ├── number_of_partitions_into_2_nonnegative_cubes.pl │ ├── number_of_partitions_into_2_positive_squares.pl │ ├── number_of_representations_as_sum_of_3_triangles.pl │ ├── number_of_representations_as_sum_of_four_squares.pl │ ├── number_of_representations_as_sum_of_two_squares.pl │ ├── number_to_digits_subquadratic_algorithm.pl │ ├── number_to_digits_subquadratic_algorithm_mpz.pl │ ├── numbers_with_pow_2_divisors.pl │ ├── omega_prime_divisors.pl │ ├── omega_prime_numbers_in_range.pl │ ├── omega_prime_numbers_in_range_mpz.pl │ ├── omega_prime_numbers_in_range_simple.pl │ ├── order_factorization_method.pl │ ├── palindrome_iteration.pl │ ├── partial_sums_of_dedekind_psi_function.pl │ ├── partial_sums_of_euler_totient_function.pl │ ├── partial_sums_of_euler_totient_function_fast.pl │ ├── partial_sums_of_euler_totient_function_fast_2.pl │ ├── partial_sums_of_euler_totient_function_times_k.pl │ ├── partial_sums_of_euler_totient_function_times_k_to_the_m.pl │ ├── partial_sums_of_exponential_prime_omega_functions.pl │ ├── partial_sums_of_gcd-sum_function.pl │ ├── partial_sums_of_gcd-sum_function_fast.pl │ ├── partial_sums_of_gcd-sum_function_faster.pl │ ├── partial_sums_of_generalized_gcd-sum_function.pl │ ├── partial_sums_of_gpf.pl │ ├── partial_sums_of_inverse_moebius_transform_of_dedekind_function.pl │ ├── partial_sums_of_jordan_totient_function.pl │ ├── partial_sums_of_jordan_totient_function_fast.pl │ ├── partial_sums_of_jordan_totient_function_times_k_to_the_m.pl │ ├── partial_sums_of_lcm_count_function.pl │ ├── partial_sums_of_liouville_function.pl │ ├── partial_sums_of_lpf.pl │ ├── partial_sums_of_n_over_k-almost_prime_divisors.pl │ ├── partial_sums_of_powerfree_numbers.pl │ ├── partial_sums_of_powerfree_part.pl │ ├── partial_sums_of_prime_bigomega_function.pl │ ├── partial_sums_of_prime_omega_function.pl │ ├── partial_sums_of_sigma0_function.pl │ ├── partial_sums_of_sigma_function.pl │ ├── partial_sums_of_sigma_function_times_k.pl │ ├── partial_sums_of_sigma_function_times_k_to_the_m.pl │ ├── partitions_count.pl │ ├── partitions_count_abs.pl │ ├── partitions_count_simple.pl │ ├── pascal-fibonacci_triangle.pl │ ├── pascal_s_triangle_multiples.pl │ ├── pattern_mixing.pl │ ├── pell_cfrac_factorization.pl │ ├── pell_factorization.pl │ ├── pell_factorization_anynum.pl │ ├── perfect_numbers.pl │ ├── period_of_continued_fraction_for_square_roots.pl │ ├── period_of_continued_fraction_for_square_roots_mpz.pl │ ├── period_of_continued_fraction_for_square_roots_ntheory.pl │ ├── phi-finder_factorization_method.pl │ ├── pi_from_infinity.pl │ ├── pisano_periods.pl │ ├── pisano_periods_efficient_algorithm.pl │ ├── pocklington-pratt_primality_proving.pl │ ├── pollard-strassen_factorization_method.pl │ ├── pollard_p-1_factorization.pl │ ├── pollard_rho_exp_factorization.pl │ ├── pollard_rho_factorization.pl │ ├── polygonal_numbers.pl │ ├── polygonal_representations.pl │ ├── polynomial_interpolation.pl │ ├── power_divisors.pl │ ├── power_of_factorial_ramanujan.pl │ ├── power_unitary_divisors.pl │ ├── powerfree_divisors.pl │ ├── powers_of_primes_in_factorial.pl │ ├── powers_of_primes_modulus_in_factorial.pl │ ├── prime_41.pl │ ├── prime_abundant_sequences.pl │ ├── prime_count_smooth_sum.pl │ ├── prime_counting_from_almost_primes.pl │ ├── prime_counting_from_squarefree_almost_primes.pl │ ├── prime_counting_liouville_formula.pl │ ├── prime_counting_mertens_formula.pl │ ├── prime_factorization_concept.pl │ ├── prime_factors_of_binomial_coefficients.pl │ ├── prime_factors_of_binomial_product.pl │ ├── prime_factors_of_factorial.pl │ ├── prime_factors_of_superfactorial_and_hyperfactorial.pl │ ├── prime_formulas.pl │ ├── prime_functions_in_terms_of_zeros_of_zeta.pl │ ├── prime_numbers_generator.pl │ ├── prime_omega_function_generalized.pl │ ├── prime_quadratic_polynomial_analyzer.pl │ ├── prime_quadratic_polynomials.pl │ ├── prime_signature_numbers_in_range.pl │ ├── prime_summation.pl │ ├── prime_zeta.pl │ ├── primes_diff.pl │ ├── primes_sum_of_pair_product.pl │ ├── primitive_sum_of_two_squares.pl │ ├── primorial_deflation.pl │ ├── pseudo_square_root.pl │ ├── pythagorean_triples.pl │ ├── quadratic-integer_factorization_method.pl │ ├── quadratic-integer_factorization_method_mpz.pl │ ├── quadratic_frobenius_primality_test.pl │ ├── quadratic_frobenius_pseudoprimes_generation.pl │ ├── quadratic_polynomial_in_terms_of_its_zeros.pl │ ├── ramanujan_sum.pl │ ├── ramanujan_sum_fast.pl │ ├── random_carmichael_fibonacci_pseudoprimes.pl │ ├── random_integer_factorization.pl │ ├── random_miller-rabin_pseudoprimes.pl │ ├── range_map.pl │ ├── rational_approximations.pl │ ├── rational_continued_fractions.pl │ ├── rational_prime_product.pl │ ├── rational_summation_of_fractions.pl │ ├── reciprocal_cycle_length.pl │ ├── rectangle_sides_from_area_and_diagonal.pl │ ├── rectangle_sides_from_diagonal_angles.pl │ ├── rectangle_sides_from_one_diagonal_angle.pl │ ├── recursive_matrix_multiplication.pl │ ├── rest_calc.pl │ ├── reversed_number_triangle.pl │ ├── reversed_number_triangles.pl │ ├── riemann_prime-counting_function.pl │ ├── riemann_s_J_function.pl │ ├── roots_on_the_rise.pl │ ├── secant_numbers.pl │ ├── semiprime_equationization.pl │ ├── semiprime_equationization_uncached.pl │ ├── sequence_analyzer.pl │ ├── sequence_closed_form.pl │ ├── sequence_polynomial_closed_form.pl │ ├── sieve_of_eratosthenes.pl │ ├── sigma0_of_factorial.pl │ ├── sigma_function.pl │ ├── sigma_of_factorial.pl │ ├── sigma_of_product_of_binomials.pl │ ├── sigma_p_adic.pl │ ├── siqs_factorization.pl │ ├── smallest_carmichael_divisible_by_n.pl │ ├── smallest_k-gonal_inverse.pl │ ├── smallest_k-gonal_inverse_brute_force.pl │ ├── smallest_lucas-carmichael_divisible_by_n.pl │ ├── smallest_number_with_at_least_n_divisors.pl │ ├── smallest_number_with_n_divisors.pl │ ├── smarandache_function.pl │ ├── smooth_numbers_generalized.pl │ ├── solutions_to_x_squared_equals_-1_mod_n.pl │ ├── solutions_to_x_squared_equals_1_mod_n.pl │ ├── solutions_to_x_squared_equals_a_mod_n.pl │ ├── solve_congruence_equation_example.pl │ ├── solve_cubic_equation.pl │ ├── solve_cubic_equation_real.pl │ ├── solve_modular_cubic_equation.pl │ ├── solve_modular_quadratic_equation.pl │ ├── solve_pell_equation.pl │ ├── solve_pell_equation_fast.pl │ ├── solve_pell_equation_generalized.pl │ ├── solve_pell_equation_simple.pl │ ├── solve_quadratic_diophantine_reciprocals.pl │ ├── solve_reciprocal_pythagorean_equation.pl │ ├── solve_sequence.pl │ ├── sophie_germain_factorization_method.pl │ ├── sorting_algorithms.pl │ ├── sphere_volume.pl │ ├── sqrt_mod_p_tonelli-shanks_mpz.pl │ ├── square_divisors.pl │ ├── square_product_subsets.pl │ ├── square_root_convergents.pl │ ├── square_root_method.pl │ ├── square_root_modulo_n_tonelli-shanks.pl │ ├── squarefree_almost_prime_divisors.pl │ ├── squarefree_almost_primes_from_factor_list.pl │ ├── squarefree_almost_primes_in_range.pl │ ├── squarefree_almost_primes_in_range_from_factor_list.pl │ ├── squarefree_almost_primes_in_range_mpz.pl │ ├── squarefree_divisors.pl │ ├── squarefree_fermat_overpseudoprimes_in_range.pl │ ├── squarefree_fermat_pseudoprimes_in_range.pl │ ├── squarefree_fermat_pseudoprimes_in_range_mpz.pl │ ├── squarefree_lucas_U_pseudoprimes_in_range.pl │ ├── squarefree_strong_fermat_pseudoprimes_in_range.pl │ ├── squarefree_strong_fermat_pseudoprimes_in_range_mpz.pl │ ├── squarefree_strong_fermat_pseudoprimes_to_multiple_bases_in_range.pl │ ├── squarefree_strong_fermat_pseudoprimes_to_multiple_bases_in_range_mpz.pl │ ├── stern_brocot_encoding.pl │ ├── stern_brocot_sequence.pl │ ├── strong_fermat_pseudoprimes_in_range.pl │ ├── strong_fermat_pseudoprimes_in_range_mpz.pl │ ├── sub-unit_squares.pl │ ├── sum_factorial.pl │ ├── sum_of_an_even_number_of_positive_squares.pl │ ├── sum_of_digits.pl │ ├── sum_of_digits_subquadratic_algorithm.pl │ ├── sum_of_digits_subquadratic_algorithm_mpz.pl │ ├── sum_of_k-powerful_numbers_in_range.pl │ ├── sum_of_natural_powers_in_constant_base.pl │ ├── sum_of_perfect_powers.pl │ ├── sum_of_prime-power_exponents_of_factorial.pl │ ├── sum_of_prime-power_exponents_of_product_of_binomials.pl │ ├── sum_of_prime_powers.pl │ ├── sum_of_primes_generalized.pl │ ├── sum_of_sigma.pl │ ├── sum_of_sigma_2.pl │ ├── sum_of_the_number_of_divisors.pl │ ├── sum_of_the_number_of_divisors_of_gcd_x_y.pl │ ├── sum_of_the_number_of_unitary_divisors.pl │ ├── sum_of_the_sum_of_divisors.pl │ ├── sum_of_three_cubes_problem.pl │ ├── sum_of_triangular_numbers_solutions.pl │ ├── sum_of_two_primes.pl │ ├── sum_of_two_squares_all_solutions.pl │ ├── sum_of_two_squares_all_solutions_2.pl │ ├── sum_of_two_squares_all_solutions_tonelli-shanks.pl │ ├── sum_of_two_squares_multiple_solutions.pl │ ├── sum_of_two_squares_solution.pl │ ├── sum_remainders.pl │ ├── super_pandigital_numbers.pl │ ├── tangent_numbers.pl │ ├── trial_division_fast.pl │ ├── triangle_hyperoperation.pl │ ├── triangle_interior_angles.pl │ ├── tribonacci_primality_test.pl │ ├── trip2mars.pl │ ├── unique_permutations.pl │ ├── unitary_divisors.pl │ ├── unitary_divisors_fast.pl │ ├── unitary_squarefree_divisors.pl │ ├── wilson_prime_formula.pl │ ├── yahtzee.pl │ ├── zequals.pl │ ├── zeta_2n.pl │ ├── zeta_for_primes.pl │ ├── zeta_function.pl │ └── zeta_prime_count_approx.pl ├── Media/ │ └── wimp-viewer ├── Microphone/ │ ├── Alsa/ │ │ └── raw_from_microphone.pl │ └── Julius/ │ ├── julius_voice_control_concept.pl │ └── voice_control.pl ├── Monitoring/ │ └── file-monitor ├── Other/ │ ├── concatenation_weirdness.pl │ ├── lexical_subs_recursion_bug.pl │ ├── tail_recursion.pl │ └── yafu_factorization.pl ├── README.md ├── Regex/ │ ├── positive-negative_matching.pl │ ├── prime_regexp.pl │ ├── regex_optimizer_in_source.pl │ ├── regex_pair_factors.pl │ └── regexp_to_strings.pl ├── Search/ │ ├── binary_search.pl │ ├── binary_search_ge.pl │ └── binary_search_le.pl ├── Shell/ │ └── execute_perl_scripts.pl ├── Simulation/ │ └── 100_prisoners_riddle.pl ├── Socket/ │ └── chat_server.pl ├── Sort/ │ ├── binsertion_sorting_algorithm.pl │ └── dream_sort.pl ├── Subtitle/ │ ├── srt-delay │ ├── srt_assembler.pl │ └── srt_fix.pl ├── Text/ │ ├── abs_string.pl │ ├── all_substrings.pl │ ├── change-encoding.pl │ ├── group_alike_words.pl │ ├── jaro-winkler_distance.pl │ ├── levenshtein_distance_iter.pl │ ├── levenshtein_distance_rec.pl │ ├── markov_chain_text_generator.pl │ ├── orthogonal_text_scrambling.pl │ ├── orthogonal_text_scrambling_double.pl │ ├── repeated_substrings.pl │ ├── search_by_prefix.pl │ ├── sim_end_words.pl │ ├── smartWordWrap.pl │ ├── smartWordWrap_lazy.pl │ ├── smartWordWrap_simple.pl │ ├── unique_prefixes.pl │ ├── word_roots.pl │ └── word_unscrambler.pl ├── Time/ │ ├── calendar.pl │ └── contdown.pl ├── Video/ │ ├── sponsor-free.pl │ ├── video_concat_ffmpeg.pl │ └── video_split_ffmpeg.pl ├── Visualisators/ │ ├── binview.pl │ ├── disk-stats.pl │ ├── dnscrypt_stats.pl │ ├── greycmd.pl │ ├── human-finder-visual.pl │ ├── lz_visual.pl │ ├── matrix_path_2-ways_best.pl │ ├── matrix_path_3-ways_best.pl │ ├── matrix_path_3-ways_greedy.pl │ ├── pview │ ├── random_finder_visual.pl │ ├── triangle_sub-string_finder.pl │ ├── visual_lz77_compression.pl │ └── visual_sudoku_dice_solver.pl └── update_readme.pl
Condensed preview — 1290 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,635K chars).
[
{
"path": ".gitignore",
"chars": 219,
"preview": "/blib/\n/.build/\n_build/\ncover_db/\ninc/\nBuild\n!Build/\nBuild.bat\n.last_cover_stats\n/Makefile\n/Makefile.old\n/MANIFEST.bak\n/"
},
{
"path": "Analyzers/char_counter.pl",
"chars": 640,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Count and list the unique characters within a file.\n\nuse strict;\nuse warnings;\nuse o"
},
{
"path": "Analyzers/chr_freq.pl",
"chars": 1086,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 30 March 2012\n# https://github.com/trizen\n\n# Count Cha"
},
{
"path": "Analyzers/dieharder.pl",
"chars": 550,
"preview": "#!/usr/bin/perl\n\n#\n## Test Perl's pseudorandom number generator with `dieharder`.\n#\n\n# usage:\n# perl dieharder.pl "
},
{
"path": "Analyzers/first_letter_top.pl",
"chars": 657,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 25 June 2016\n# Website: https://github.com/tri"
},
{
"path": "Analyzers/kcal/kcal.pl",
"chars": 1291,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 13 February 2015\n# Website: https://github.com"
},
{
"path": "Analyzers/kcal/products.csv",
"chars": 418,
"preview": "name, kcal/100g, price/100g\nMilk (1.5% fat),44,0.3\nDark chocolate (50% cacao),519,2.7\nMustard,178,0.93\nMountain dew,52,0"
},
{
"path": "Analyzers/kernel_config_diff.pl",
"chars": 1604,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 16 March 2013\n# https://github.com/trizen\n\n# List acti"
},
{
"path": "Analyzers/perl_code_analyzer.pl",
"chars": 4137,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 04 January 2015\n# Website: https://github.com/"
},
{
"path": "Analyzers/perl_code_spellcheck.pl",
"chars": 6042,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 29 January 2017\n# https://github.com/trizen\n\n# Checks "
},
{
"path": "Analyzers/reptop.pl",
"chars": 2498,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 29 November 2011\n# Edit: 03 November 2012\n# https://gi"
},
{
"path": "Analyzers/text_stats.pl",
"chars": 2106,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 15 June 2013\n# https://github.com/trizen\n\n#\n## This sc"
},
{
"path": "Analyzers/unidecode_word_top.pl",
"chars": 588,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 11 March 2013\n# https://github.com/trizen\n\n# usage: pe"
},
{
"path": "Analyzers/wcer.pl",
"chars": 204,
"preview": "#!/usr/bin/perl\n\n# Count words in a text file\n# Coded by Trizen under GPL.\n# usage: cat file.txt | perl wcer\n# pe"
},
{
"path": "Analyzers/word_suffix_top.pl",
"chars": 794,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 05 April 2015\n# https://github.com/trizen\n\n# W"
},
{
"path": "Audio/auto-mp3tags.pl",
"chars": 1210,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 15 August 2011\n# Edit: 11 August 2019\n# https://github"
},
{
"path": "Audio/group_audio_files.pl",
"chars": 2932,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 11 August 2019\n# https://github.com/trizen\n\n# Group MP"
},
{
"path": "Audio/mkv_audio_to_opus.pl",
"chars": 1715,
"preview": "#!/usr/bin/perl\n\n# Convert MKV audio files to OPUS files, in a given directory (and its subdirectories).\n\n# Requires `ff"
},
{
"path": "Audio/recompress_audio_track.pl",
"chars": 2975,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 06 September 2023\n# https://github.com/trizen\n\n# Make video files smaller, by "
},
{
"path": "Audio/rem-mp3tags.pl",
"chars": 1422,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 15 August 2011\n# Edit: 11 August 2019\n# https://github"
},
{
"path": "Audio/wave-cmp.pl",
"chars": 7583,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 22 March 2015\n# Website: https://github.com/tr"
},
{
"path": "Audio/wave-cmp2.pl",
"chars": 6792,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 22 March 2015\n# Edit: 04 September 2015\n# Webs"
},
{
"path": "Benchmarks/array_range_vs_shift.pl",
"chars": 732,
"preview": "#!/usr/bin/perl\n\nuse 5.014;\n\nuse Benchmark qw(cmpthese);\n\npackage Foo {\n\n sub new {\n bless {}, __PACKAGE__;\n "
},
{
"path": "Benchmarks/compression_algorithms.pl",
"chars": 2770,
"preview": "#!/usr/bin/perl\n\n# Rough performance comparison of some compression modules on a given file given as an argument.\n\nuse 5"
},
{
"path": "Benchmarks/json_vs_storable.pl",
"chars": 1404,
"preview": "#!/usr/bin/perl\n\n# Speed comparison of JSON::XS vs Storable.\n\n# Result:\n# Storable is significantly faster for both en"
},
{
"path": "Benchmarks/schwartzian_transform.pl",
"chars": 808,
"preview": "#!/usr/bin/perl\n\n# Performance comparison of Schwartzian transform.\n\n# See also:\n# https://en.wikipedia.org/wiki/Schwa"
},
{
"path": "Benchmarks/types_of_variables.pl",
"chars": 571,
"preview": "#!/usr/bin/perl\n\n# Performance comparison between `state`, `my` and global variables.\n\nuse 5.010;\nuse Benchmark qw(cmpth"
},
{
"path": "Book tools/rosettacode_to_markdown.pl",
"chars": 13450,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 24 April 2015\n# Edit: 09 December 2023\n# Websi"
},
{
"path": "Book tools/update_summary.pl",
"chars": 2993,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 24 April 2015\n# Website: https://github.com/tr"
},
{
"path": "Compression/High-level/ablz_file_compression.pl",
"chars": 4784,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 31 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/bbwr_file_compression.pl",
"chars": 4739,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 04 July 2024\n# https://github.com/trizen\n\n# Compress/decompress files using Bi"
},
{
"path": "Compression/High-level/blzss2_file_compression.pl",
"chars": 4954,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 29 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/blzss_file_compression.pl",
"chars": 4928,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 25 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/brlzss_file_compression.pl",
"chars": 5415,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 25 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/bwac_file_compression.pl",
"chars": 3696,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 13 April 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwad_file_compression.pl",
"chars": 3700,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlz2_file_compression.pl",
"chars": 5084,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 13 April 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlz3_file_compression.pl",
"chars": 4626,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 02 May 2024\n# https://github.com/trizen\n\n# Compress/decom"
},
{
"path": "Compression/High-level/bwlz_file_compression.pl",
"chars": 4996,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlza2_file_compression.pl",
"chars": 5848,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlza_file_compression.pl",
"chars": 5195,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlzad2_file_compression.pl",
"chars": 5849,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlzad_file_compression.pl",
"chars": 5352,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 07 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwlzb_file_compression.pl",
"chars": 4592,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 03 June 2024\n# https://github.com/trizen\n\n# Compress/decompress files using by"
},
{
"path": "Compression/High-level/bwlzhd2_file_compression.pl",
"chars": 4716,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 25 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/bwlzhd_file_compression.pl",
"chars": 4780,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/High-level/bwlzss_file_compression.pl",
"chars": 4217,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwrl2_file_compression.pl",
"chars": 5260,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 13 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/bwrm2_file_compression.pl",
"chars": 4825,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 13 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/bwrm_file_compression.pl",
"chars": 4809,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 13 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/bwt2_file_compression.pl",
"chars": 3678,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bwt_file_compression.pl",
"chars": 3537,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/bzip2_file_compression.pl",
"chars": 2802,
"preview": "#!/usr/bin/perl\n\n# Compress files using Bzip2.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(basenam"
},
{
"path": "Compression/High-level/gzip_file_compression.pl",
"chars": 2784,
"preview": "#!/usr/bin/perl\n\n# Compress files using Gzip.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(basename"
},
{
"path": "Compression/High-level/hblz_file_compression.pl",
"chars": 4913,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 31 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/lz255_file_compression.pl",
"chars": 3555,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 01 September 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/High-level/lz2ss_file_compression.pl",
"chars": 3557,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lz4_file_compression.pl",
"chars": 2886,
"preview": "#!/usr/bin/perl\n\n# Compress files using LZ4.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(b"
},
{
"path": "Compression/High-level/lz772_file_compression.pl",
"chars": 3551,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lz77_file_compression.pl",
"chars": 3473,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/High-level/lz77f_file_compression.pl",
"chars": 3523,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lzac_file_compression.pl",
"chars": 4379,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/High-level/lzb_file_compression.pl",
"chars": 3902,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 May 2024\n# https://github.com/trizen\n\n# Compress/decompress files using LZ7"
},
{
"path": "Compression/High-level/lzbbw_file_compression.pl",
"chars": 4312,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 04 June 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lzbf_file_compression.pl",
"chars": 3826,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 May 2024\n# https://github.com/trizen\n\n# Compress/decompress files using LZ7"
},
{
"path": "Compression/High-level/lzbh_file_compression.pl",
"chars": 6722,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 24 May 2024\n# https://github.com/trizen\n\n# Compress/decompress files using LZ7"
},
{
"path": "Compression/High-level/lzbw2_file_compression.pl",
"chars": 7035,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/lzbw3_file_compression.pl",
"chars": 4149,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 29 May 2024\n# https://github.com/trizen\n\n# Compress/decompress files using LZ7"
},
{
"path": "Compression/High-level/lzbw4_file_compression.pl",
"chars": 4205,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 01 September 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/High-level/lzbw5_file_compression.pl",
"chars": 4702,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 04 September 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/High-level/lzbw_file_compression.pl",
"chars": 6434,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/lzbwa_file_compression.pl",
"chars": 7046,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/lzbwad_file_compression.pl",
"chars": 7129,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/lzbwd_file_compression.pl",
"chars": 8017,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 07 September 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/lzbwh_file_compression.pl",
"chars": 6678,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 07 September 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/High-level/lzbws_file_compression.pl",
"chars": 3475,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 25 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lzhd2_file_compression.pl",
"chars": 4172,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 01 September 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/High-level/lzhd_file_compression.pl",
"chars": 4095,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/High-level/lzih_file_compression.pl",
"chars": 4069,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 13 June 2023\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lzmrl2_file_compression.pl",
"chars": 4115,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 25 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lzmrl_file_compression.pl",
"chars": 3483,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/lzop_file_compression.pl",
"chars": 2794,
"preview": "#!/usr/bin/perl\n\n# Compress files using Lzop.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(basename"
},
{
"path": "Compression/High-level/lzsbw_file_compression.pl",
"chars": 3799,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/lzss2_file_compression.pl",
"chars": 3927,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/lzss77_file_compression.pl",
"chars": 3932,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/lzss_file_compression.pl",
"chars": 3868,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/lzssf_file_compression.pl",
"chars": 3842,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 21 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/lzssm_file_compression.pl",
"chars": 3870,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 23 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/lzw_file_compression.pl",
"chars": 3463,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 08 December 2022\n# Edit: 15 June 2023\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/High-level/mblz_file_compression.pl",
"chars": 4790,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 31 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/mbwr_file_compression.pl",
"chars": 3949,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 13 April 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/High-level/mrl_file_compression.pl",
"chars": 3382,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 August 2024\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/High-level/mybzip2_file_compression.pl",
"chars": 3220,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Edit: 21 August 2024\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/High-level/mygzip_file_compression.pl",
"chars": 3094,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Edit: 22 August 2024\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/High-level/mygzipf_file_compression.pl",
"chars": 3228,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Edit: 22 August 2024\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/High-level/mylz4_file_compression.pl",
"chars": 3167,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Edit: 25 August 2024\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/High-level/mylz4f_file_compression.pl",
"chars": 3210,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Edit: 25 August 2024\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/High-level/myzlib_file_compression.pl",
"chars": 3062,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Edit: 06 November 2024\n# https://github.com/trizen\n\n# Compress/decompress files usin"
},
{
"path": "Compression/High-level/rablz_file_compression.pl",
"chars": 4936,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 31 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/rlzss_file_compression.pl",
"chars": 3986,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 25 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/High-level/sbwt_file_compression.pl",
"chars": 5615,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# Date: 09 November 2024\n# https://github.com/trizen\n\n# Compress/decomp"
},
{
"path": "Compression/High-level/xz_file_compression.pl",
"chars": 2782,
"preview": "#!/usr/bin/perl\n\n# Compress files using XZ/LZMA.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(basen"
},
{
"path": "Compression/High-level/zlib_file_compression.pl",
"chars": 2522,
"preview": "#!/usr/bin/perl\n\n# Compress files using Gzip.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(basename"
},
{
"path": "Compression/High-level/zstd_file_compression.pl",
"chars": 2799,
"preview": "#!/usr/bin/perl\n\n# Compress files using Zstandard.\n\nuse 5.036;\nuse Getopt::Std qw(getopts);\nuse File::Basename qw(bas"
},
{
"path": "Compression/bbwr_file_compression.pl",
"chars": 8066,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bqof_file_compression.pl",
"chars": 6386,
"preview": "#!/usr/bin/perl\n\n# A general purpose lossless compressor, based on ideas from the QOI compressor. (+BWT)\n\n# See also:\n# "
},
{
"path": "Compression/bwac_file_compression.pl",
"chars": 17165,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 06 February 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/bwad_file_compression.pl",
"chars": 17393,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 06 February 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/bwaz_file_compression.pl",
"chars": 16220,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 14 July 2023\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/bwlz2_file_compression.pl",
"chars": 24517,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bwlz_file_compression.pl",
"chars": 22242,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 20 June 2023\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/bwlza2_file_compression.pl",
"chars": 20740,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bwlza_file_compression.pl",
"chars": 24694,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 06 February 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/bwlzad2_file_compression.pl",
"chars": 20867,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bwlzad_file_compression.pl",
"chars": 24768,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 07 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bwlzhd_file_compression.pl",
"chars": 13969,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/bwlzss_file_compression.pl",
"chars": 18673,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bwrl2_file_compression.pl",
"chars": 17035,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 29 February 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/bwrl_file_compression.pl",
"chars": 16845,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# https://github.com/trizen\n\n# Compress/decompress files usi"
},
{
"path": "Compression/bwrla_file_compression.pl",
"chars": 19298,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 23 February 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/bwrlz2_file_compression.pl",
"chars": 23978,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/bwrlz_file_compression.pl",
"chars": 20042,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 29 February 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/bwrm_file_compression.pl",
"chars": 16618,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 10 September 2023\n# Edit: 29 February 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/bwt2_file_compression.pl",
"chars": 17788,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/bwt_file_compression.pl",
"chars": 17857,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 25 February 2026\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/bww_file_compression.pl",
"chars": 16535,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 June 2023\n# Edit: 16 June 2023\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/bzip2_compressor.pl",
"chars": 3813,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 20 August 2024\n# https://github.com/trizen\n\n# A very basic Bzip2 compressor.\n\n"
},
{
"path": "Compression/bzip2_decompressor.pl",
"chars": 7230,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 19 August 2024\n# https://github.com/trizen\n\n# A very basic Bzip2 decompressor."
},
{
"path": "Compression/bzip2_file_compression.pl",
"chars": 15004,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 25 August 2024\n# https://github.com/trizen\n\n# A valid Bzip2 file compressor/de"
},
{
"path": "Compression/compress.pl",
"chars": 2170,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 May 2023\n# https://github.com/trizen\n\n# A basic implementation of the UNIX "
},
{
"path": "Compression/gzip2_file_compression.pl",
"chars": 8942,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 May 2024\n# Edit: 06 November 2024\n# https://github.com/trizen\n\n# A valid Gz"
},
{
"path": "Compression/gzip_block_type_1.pl",
"chars": 3974,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# Edit: 05 April 2024\n# https://github.com/trizen\n\n# Create a "
},
{
"path": "Compression/gzip_block_type_1_huffman_only.pl",
"chars": 2444,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# Edit: 05 April 2024\n# https://github.com/trizen\n\n# Create a "
},
{
"path": "Compression/gzip_block_type_2.pl",
"chars": 8791,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# Edit: 11 April 2024\n# https://github.com/trizen\n\n# Create a "
},
{
"path": "Compression/gzip_block_type_2_huffman_only.pl",
"chars": 4554,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# Edit: 09 April 2024\n# https://github.com/trizen\n\n# Create a "
},
{
"path": "Compression/gzip_block_type_2_simple.pl",
"chars": 6778,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# Edit: 09 April 2024\n# https://github.com/trizen\n\n# Create a "
},
{
"path": "Compression/gzip_comment.pl",
"chars": 5585,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 21 January 2024\n# https://github.com/trizen\n\n# Add and extract a GZIP comment,"
},
{
"path": "Compression/gzip_decompressor.pl",
"chars": 11931,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# Edit: 14 April 2024\n# https://github.com/trizen\n\n# Decompres"
},
{
"path": "Compression/gzip_file_compression.pl",
"chars": 24511,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 May 2024\n# https://github.com/trizen\n\n# A valid Gzip file compressor/decomp"
},
{
"path": "Compression/gzip_store.pl",
"chars": 1955,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 January 2024\n# https://github.com/trizen\n\n# Create a valid Gzip container, "
},
{
"path": "Compression/hfm_file_compression.pl",
"chars": 7610,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 01 December 2022\n# Edit: 28 April 2023\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/lz4_compressor.pl",
"chars": 3191,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 23 August 2024\n# https://github.com/trizen\n\n# A simple LZ4 compressor.\n\n# Refe"
},
{
"path": "Compression/lz4_decompressor.pl",
"chars": 5243,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 09 May 2024\n# Edit: 08 July 2024\n# https://github.com/trizen\n\n# A simple LZ4 d"
},
{
"path": "Compression/lz4_file_compression.pl",
"chars": 10407,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 25 August 2024\n# https://github.com/trizen\n\n# A valid LZ4 file compressor/deco"
},
{
"path": "Compression/lz77_file_compression.pl",
"chars": 4381,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# https://github.com/trizen\n\n# Compress/decompress files usin"
},
{
"path": "Compression/lza_file_compression.pl",
"chars": 12109,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/lzac_file_compression.pl",
"chars": 12935,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 06 February 2024\n# https://github.com/trizen\n\n# Compr"
},
{
"path": "Compression/lzaz_file_compression.pl",
"chars": 11829,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 12 August 2023\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/lzb2_file_compression.pl",
"chars": 8739,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 11 May 2024\n# Edit: 02 June 2024\n# https://github.com/trizen\n\n# Compress/decom"
},
{
"path": "Compression/lzb_file_compression.pl",
"chars": 8718,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 11 May 2024\n# https://github.com/trizen\n\n# Compress/decompress files using LZ7"
},
{
"path": "Compression/lzbf2_file_compression.pl",
"chars": 8041,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 11 May 2024\n# Edit: 02 June 2024\n# https://github.com/trizen\n\n# Compress/decom"
},
{
"path": "Compression/lzbf_file_compression.pl",
"chars": 8021,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 11 May 2024\n# https://github.com/trizen\n\n# Compress/decompress files using LZ7"
},
{
"path": "Compression/lzbh_file_compression.pl",
"chars": 14516,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 11 May 2024\n# Edit: 02 June 2024\n# https://github.com/trizen\n\n# Compress/decom"
},
{
"path": "Compression/lzbw_file_compression.pl",
"chars": 19916,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# https://github.com/trizen\n\n# Compress/decompress files usi"
},
{
"path": "Compression/lzbwa_file_compression.pl",
"chars": 22362,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# Edit: 23 February 2024\n# https://github.com/trizen\n\n# Comp"
},
{
"path": "Compression/lzbwad_file_compression.pl",
"chars": 22450,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 September 2023\n# Edit: 07 March 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/lzbwd_file_compression.pl",
"chars": 19975,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 07 September 2023\n# https://github.com/trizen\n\n# Compress/decompress files usi"
},
{
"path": "Compression/lzbwh_file_compression.pl",
"chars": 19843,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 07 September 2023\n# https://github.com/trizen\n\n# Compress/decompress files usi"
},
{
"path": "Compression/lzh_file_compression.pl",
"chars": 9698,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress"
},
{
"path": "Compression/lzhc_file_compression.pl",
"chars": 8528,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Created on: 21 May 2014\n# Latest edit on: 26 April 2"
},
{
"path": "Compression/lzhd_file_compression.pl",
"chars": 10481,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 13 June 2023\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/lzih_file_compression.pl",
"chars": 10707,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 15 December 2022\n# Edit: 13 June 2023\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/lzsa_file_compression.pl",
"chars": 16773,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 12 August 2023\n# https://github.com/trizen\n\n# Compress/de"
},
{
"path": "Compression/lzsad_file_compression.pl",
"chars": 17619,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 07 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/lzsbw_file_compression.pl",
"chars": 18899,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 18 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/lzss2_file_compression.pl",
"chars": 15051,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 20 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/lzss_file_compression.pl",
"chars": 14327,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# https://github.com/trizen\n\n# Compress/decompress files using LZ"
},
{
"path": "Compression/lzssf_file_compression.pl",
"chars": 14039,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 02 May 2024\n# https://github.com/trizen\n\n# Compress/decom"
},
{
"path": "Compression/lzsst2_file_compression.pl",
"chars": 16640,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 04 July 2024\n# https://github.com/trizen\n\n# Compress/deco"
},
{
"path": "Compression/lzsst_file_compression.pl",
"chars": 14662,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 02 May 2024\n# https://github.com/trizen\n\n# Compress/decom"
},
{
"path": "Compression/lzt2_file_compression.pl",
"chars": 5139,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Created on: 21 May 2014\n# Latest edit on: 28 May 201"
},
{
"path": "Compression/lzt_file_compression.pl",
"chars": 5182,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Created on: 21 May 2014\n# Latest edit on: 28 May 201"
},
{
"path": "Compression/lzw_file_compression.pl",
"chars": 8299,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 08 December 2022\n# Edit: 15 June 2023\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/mbwr_file_compression.pl",
"chars": 15097,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/mra_file_compression.pl",
"chars": 15133,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 29 February 2024\n# https://github.com/trizen\n\n# Compress/"
},
{
"path": "Compression/mrh_file_compression.pl",
"chars": 12819,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 14 June 2023\n# Edit: 15 August 2023\n# https://github.com/trizen\n\n# Compress/de"
},
{
"path": "Compression/mrlz_file_compression.pl",
"chars": 18846,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 17 June 2023\n# Edit: 19 March 2024\n# https://github.com/trizen\n\n# Compress/dec"
},
{
"path": "Compression/ppmh_file_compression.pl",
"chars": 16344,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 11 August 2023\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/qof_file_compression.pl",
"chars": 6038,
"preview": "#!/usr/bin/perl\n\n# A general purpose lossless compressor, based on ideas from the QOI compressor.\n\n# See also:\n# https"
},
{
"path": "Compression/rans_file_compression.pl",
"chars": 8129,
"preview": "#!/usr/bin/perl\n\n# File compression with rANS encoding, using big integers.\n\n# Reference:\n# Stanford EE274: Data Comp"
},
{
"path": "Compression/rlac_file_compression.pl",
"chars": 12158,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 August 2023\n# Edit: 06 February 2024\n# https://github.com/trizen\n\n# Compres"
},
{
"path": "Compression/rlh_file_compression.pl",
"chars": 9526,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 13 August 2023\n# https://github.com/trizen\n\n# Compress/decompress files using "
},
{
"path": "Compression/tac_file_compression.pl",
"chars": 6061,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 01 May 2015\n# Website: https://github.com/triz"
},
{
"path": "Compression/tacc_file_compression.pl",
"chars": 8106,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# Date: 11 February 2016\n# Edit: 14 July 2023\n# https://github.com/trizen\n\n# Ar"
},
{
"path": "Compression/test_compressors.pl",
"chars": 6504,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 19 March 2024\n# https://github.com/trizen\n\nuse 5.036;\nuse File::Temp "
},
{
"path": "Compression/tzip2_file_compression.pl",
"chars": 7633,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 12 August 2013\n# Website: https://trizenx.blog"
},
{
"path": "Compression/tzip_file_compression.pl",
"chars": 6458,
"preview": "#!/usr/bin/perl\n\n# Author: Șuteu \"Trizen\" Daniel\n# License: GPLv3\n# Date: 12 August 2013\n# Website: https://trizenx.blog"
},
{
"path": "Compression/unzip.pl",
"chars": 7508,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# Date: 20 November 2024\n# https://github.com/trizen\n\n# Basic implement"
},
{
"path": "Compression/zip.pl",
"chars": 8532,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# Date: 03 February 2025\n# Edit: 04 February 2025\n# https://github.com/"
},
{
"path": "Compression/zlib_compressor.pl",
"chars": 1627,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# Date: 05 November 2024\n# https://github.com/trizen\n\n# Basic implement"
},
{
"path": "Compression/zlib_decompressor.pl",
"chars": 1991,
"preview": "#!/usr/bin/perl\n\n# Author: Daniel \"Trizen\" Șuteu\n# Date: 06 November 2024\n# https://github.com/trizen\n\n# Basic decompres"
},
{
"path": "Compression/zlib_file_compression.pl",
"chars": 5250,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 05 May 2024\n# Edit: 06 November 2024\n# https://github.com/trizen\n\n# A valid Gz"
},
{
"path": "Converters/another_notes_to_markdown.pl",
"chars": 1427,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 27 April 2024\n# https://github.com/trizen\n\n# Convert JSON data from the Androi"
},
{
"path": "Converters/another_notes_to_material_notes.pl",
"chars": 2335,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 27 April 2024\n# Edit: 28 September 2024\n# https://github.com/trizen\n\n# Convert"
},
{
"path": "Converters/any_to_3gp.pl",
"chars": 1758,
"preview": "#!/usr/bin/perl\n\n# Daniel \"Trizen\" Șuteu\n# License: GPLv3\n# Date: 10 June 2013\n# https://github.com/trizen\n\n#\n## Convert"
},
{
"path": "Converters/ass2srt.pl",
"chars": 3183,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 01 February 2022\n# https://github.com/trizen\n\n# Convert ASS/SSA subtitles to S"
},
{
"path": "Converters/code2pdf.pl",
"chars": 10589,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 30 July 2022\n# https://github.com/trizen\n\n# Code to PDF converter, with syntax"
},
{
"path": "Converters/euler2pdf.pl",
"chars": 3048,
"preview": "#!/usr/bin/perl\n\nuse 5.010;\nuse strict;\nuse warnings;\n\nuse PDF::API2 qw();\nuse Text::Unidecode qw(unid"
},
{
"path": "Converters/from_hex.pl",
"chars": 534,
"preview": "#!/usr/bin/perl\n\n# Convert HEX to binary.\n\nuse 5.020;\nuse strict;\nuse warnings;\n\nuse Getopt::Long qw(GetOptions);\n\nmy $l"
},
{
"path": "Converters/gdbm_to_berkeley.pl",
"chars": 818,
"preview": "#!/usr/bin/perl\n\n# Author: Trizen\n# Date: 03 April 2023\n# https://github.com/trizen\n\n# Convert a GDBM database to a Berk"
}
]
// ... and 1090 more files (download for full content)
About this extraction
This page contains the full source code of the trizen/perl-scripts GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1290 files (4.2 MB), approximately 1.2M tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.