//! Cipher Identification Module
//!
//! This module contains the main algorithm for identifying ciphers based on statistical tests.
use std::cmp::Ordering;
/// A type alias for a cipher score pair
pub type CipherScore = (String, f64);
/// Calculates the z-score for each cipher type using the cipher statistics
/// and the average and standard deviation values for each cipher type.
///
/// # Arguments
///
/// * `cipher_stats` - A slice of f64 values representing the results of statistical tests
/// * `cipher_types` - A slice of strings representing the cipher types to check
///
/// # Returns
///
/// A vector of (cipher_type, score) pairs, where lower scores indicate better matches
///
/// # Examples
///
/// ```
/// use cipher_identifier::identify_cipher::get_cipher;
///
/// let cipher_stats = vec![36.5, 48.9, 64.9, 16.5, 17.4, 4.9, 48.1, 279.1, 68.2];
/// let cipher_types = vec!["6x6bifid".to_string(), "Autokey".to_string()];
/// let scores = get_cipher(&cipher_stats, &cipher_types);
/// assert_eq!(scores.len(), 2);
/// ```
pub fn get_cipher(cipher_stats: &[f64], cipher_types: &[String]) -> Vec<CipherScore> {
// These values are from the original Python code
// They represent the average and standard deviation values for each statistical test
// for each cipher type
// Average values for each test for each cipher type
#[rustfmt::skip]
let average = [
// IOC
vec![36.29959009564019, 38.77773874444502, 39.41748832430962, 47.34203488465864, 46.202186681671414, 45.62871914185703, 57.337686454076234, 60.285190665870964, 56.52971169612065, 56.72801622755119, 56.75363622588858, 56.03261070602987, 54.50476841359461, 53.288672553858056, 52.262262947561396, 51.84691692946594, 53.44545359635517, 53.27424656657473, 52.061091305575104, 53.14573347900599, 52.695119891255565, 53.10843819067592, 55.50505572947793, 55.059863461049666, 55.70312801878728, 55.69104859202235, 55.43961514620477, 55.026853702631364, 54.61056167478138, 54.93423558306198, 56.38430814293194, 59.18461540253375, 62.31544099673388, 63.380626108783986, 63.4373859403754, 62.851780950128585, 64.35366048148126, 64.32152218022621, 67.68896978978913, 67.25282243863727, 66.77142678125294, 66.32041193758484, 66.95615347594716, 66.59801583895089, 66.14066088828463, 65.22664594977611, 64.53906753159707, 64.57068139101855, 64.58476380615127, 64.05472516823858, 64.05148059437704, 63.77384681068497, 63.78646627328237, 64.53533157304925, 65.85478744751319, 65.53768913360008, 65.02727542267182, 64.47187757547844],
// MIC
vec![48.89643046023051, 52.90715736122677, 60.06411731603032, 64.81072043812343, 66.01366092598056, 64.1036804059243, 74.47585887911325, 76.81036634970657, 72.08051126777325, 72.34242601868536, 72.37577790198249, 72.25001942118405, 71.90613877792552, 71.48225321238021, 71.18996368181273, 70.84568600892588, 71.98076590515105, 71.90856507222543, 71.67716621306157, 72.5374695463771, 71.66966161179705, 71.94312603594857, 76.62295176935957, 75.71552846887194, 76.19175869852755, 76.17901942639786, 75.77771249267805, 75.26711993892012, 74.37275162787691, 75.26813700629764, 76.58279987707229, 79.78684134148146, 82.98196362372825, 84.09544850010143, 83.9777793635822, 83.14013435048832, 85.48458520696471, 85.57973825523204, 90.02072758787021, 89.42138920191411, 88.5896984182335, 88.0945699241854, 88.53139789927062, 88.25599254298189, 87.63242770800414, 86.37459175270969, 85.43680772918455, 85.5537817683555, 85.76957930685504, 85.86043586381719, 85.72354851770447, 85.25677694765088, 85.3221756135296, 86.06769577165024, 87.52827355142273, 87.0757169558271, 86.26386670471865, 85.62760704520839],
// MKA
vec![64.90090785254274, 70.64740058657578, 81.75191688504458, 86.66498263793089, 85.72753611182787, 84.0156862806312, 94.69513137885242, 97.0645280163769, 92.42747007818487, 92.61936437725566, 92.63829438100879, 92.0228233358347, 90.76289175800761, 89.60599546075657, 88.65641877071678, 88.1857302938981, 90.36565435181681, 90.32062107882821, 89.51215905147072, 91.38585111729188, 90.92086833801355, 91.55821132358291, 96.61847555009138, 95.68206801232009, 96.95906386329396, 96.93428776527956, 96.42696879632189, 96.0573799641954, 95.21036470256993, 96.2596346914409, 97.76705890124074, 101.41214280247415, 105.34431384638792, 106.72475309511816, 106.74234245079684, 105.9925981158862, 108.05511809202306, 108.19544024616732, 112.60802305323186, 111.9996420547133, 111.0820227776097, 110.52881131394716, 111.04342970270949, 110.66639310083848, 110.02062892211138, 108.68027940429133, 107.99076899021422, 108.2856083922911, 108.5736125610839, 108.75843090503452, 108.79896020193303, 108.30381212455306, 108.39083565349291, 109.12548648202771, 110.9129501220803, 110.4372368479654, 109.3627990510722, 108.6773190689771],
// DIC
vec![16.487138568252636, 24.149800158164002, 21.756094825735513, 35.14072089680284, 32.14244220451914, 32.076826774253284, 52.72392699103262, 56.69984006027152, 49.353569053931835, 49.67801367669241, 49.76902794584931, 48.52395761973365, 45.73040338056564, 43.455041682464, 41.5648704951356, 40.70560444223262, 40.668021187381356, 40.44310676489167, 38.57157416142799, 39.26301736550856, 38.11992557974812, 38.30328086223677, 43.96853910428493, 42.94806653853386, 43.07254733787836, 43.05251558636127, 42.58549894957279, 42.264391877011604, 42.324833512933026, 42.33868477377385, 44.6208962192118, 50.43607215921695, 60.27364220012391, 62.67584298997652, 62.02683234468383, 60.85026266781766, 63.802695440143076, 63.43811466495743, 70.3069360193056, 69.47506502233121, 68.46984935033889, 67.65576653393748, 68.55597474594764, 67.92636481781338, 66.98732131108218, 65.25850259486769, 63.91703446397629, 63.311011548857756, 62.959889989478455, 62.01598193048084, 61.501961021440096, 60.838930448106225, 61.16689712999895, 62.94308611562635, 66.05219308045893, 65.36655619264664, 64.34639926915625, 63.44540387154473],
// EDI
vec![17.437469424349487, 43.245123378000244, 33.12731853229944, 42.53691056228856, 38.72291402877138, 36.51256263492719, 63.35194480703612, 68.79471331871402, 59.32123284733261, 59.74179375439843, 59.96447643888715, 58.317025010688695, 54.8245792422093, 51.93426816734669, 49.63551532113745, 48.83168953797709, 47.84248074440095, 47.56510063518901, 45.295792394883264, 45.262694094207156, 43.68460652621176, 43.67742924089723, 56.60569082246857, 54.93226627461317, 54.1765817843597, 54.13594661149581, 53.53902457225294, 54.80884694804432, 54.25067328546377, 53.656837208517025, 56.810846437486944, 62.06169026691783, 71.5740111481126, 73.77830709883301, 72.67660119112298, 71.2259092887254, 75.10115694090892, 74.67056479512313, 87.40018098198216, 86.33830158611566, 84.84887437723357, 84.54234131883479, 85.21430493760043, 84.35397319889299, 83.13014206090531, 80.88457565353279, 79.0651347722554, 78.08555476029643, 77.44643840380459, 76.18822532871529, 75.35985035946214, 74.41651893466484, 74.45025717636199, 78.51679477432967, 81.23179382180737, 80.28849637344395, 78.92303684438949, 78.94029015411364],
// LR
vec![4.931484792330411, 7.579713418488182, 5.379583667245949, 9.465874715925624, 8.952752791358362, 9.46413315812323, 12.719497112489332, 13.435275733370531, 11.58547012168674, 11.641712633684381, 11.651308945272957, 11.557245133034945, 11.237865134655319, 11.078709196427134, 10.926462516675853, 10.665860154916075, 10.540562000755662, 10.480416756910381, 10.103089317087528, 10.156958756798891, 9.898974515342859, 9.930543895943376, 10.994785897240758, 10.78688432808963, 10.770598545289698, 10.762223246627585, 10.63324458997454, 10.640458439361266, 10.919915314988819, 10.773378395724619, 11.1761863283826, 12.152737080007432, 13.73603612986118, 14.168046379130873, 14.045042202265845, 13.808360674067549, 14.245298935485641, 14.143283588634025, 15.277266486097174, 15.092564578790869, 14.973462982848583, 14.9168218319277, 15.079980746857437, 14.944677777482806, 14.731896432283907, 14.351652537162561, 14.058175343595533, 13.907462640676338, 13.803834560990936, 13.53601725332998, 13.438929389440474, 13.324187434098993, 13.515303931023531, 13.818061154203379, 14.357180939078296, 14.222425171246721, 14.067194405521615, 13.976869247699446],
// ROD
vec![48.10980949339963, 36.67911588920848, 43.22801234383587, 45.77976268545847, 45.06584580368633, 46.43597287546429, 46.06588711539855, 45.917720052767706, 46.81918640382419, 46.80965114213168, 46.79193040255441, 46.820271626490985, 46.3732637126398, 46.03316141243024, 45.76050171872369, 45.413007993537, 46.092629771085015, 46.08352050550604, 46.03948872432293, 46.564815726622776, 46.80674578747873, 46.990280499376354, 45.05927830858463, 45.34733549868309, 45.819210963321076, 45.82550718567123, 45.76163466808595, 44.58777765121324, 44.86419934685346, 45.18871283285563, 45.11230261037369, 45.34261136941958, 45.57644151858795, 45.64821271465264, 45.82130173166595, 45.94184919326338, 45.814420126669994, 45.82148806062053, 45.03759789776844, 45.11307839416246, 45.22182339393876, 44.8700061187183, 44.94643302514641, 44.92251004116349, 45.00553848760578, 45.17358980215646, 45.348873622254274, 45.49766762738041, 45.566787259402474, 45.52624945409049, 45.598693216940035, 45.70545581988821, 45.824288157495985, 45.55330291805502, 45.67561167469752, 45.78523305597289, 45.88559487988558, 45.094660759267654],
// LDI
vec![279.09002856836383, 247.90245173461875, 315.0775320561718, 366.01834062992594, 385.27604934443787, 392.15472952449153, 336.613501737761, 314.3524885967868, 334.9172162495736, 333.81732391377864, 333.9709857113104, 339.00279229927787, 348.2433870539949, 356.3245965115224, 363.43133087207497, 366.3968621963182, 404.46067493516176, 404.7864694586666, 407.8937051301993, 431.2863907017286, 438.6336050145827, 445.6947682252808, 455.1982181549145, 455.01739633576636, 468.5804792230917, 468.5587246047304, 468.7757890055819, 468.3871657281597, 466.95732611499335, 474.465950356787, 459.7555298690939, 468.7332963567426, 446.04628916775886, 437.93635663743595, 445.50648041529786, 445.42007829545344, 437.0992304736932, 440.7581417407066, 422.24819824334025, 422.3341855147891, 422.9140304484714, 424.72073295647164, 418.3045905210044, 418.6529004642857, 419.2413449559489, 419.5348131878873, 421.0376023647122, 427.8514518079852, 432.73468896180117, 433.07628341832674, 438.46477161278983, 439.66202088071446, 439.32099947131064, 432.78247805244075, 422.8010320808126, 423.33685069957556, 424.85085768652357, 427.257178529112],
// SDD
vec![68.24480234601343, 61.590402090609174, 78.25709135005972, 88.55362128490044, 95.6756408640571, 98.93349400947214, 84.92145408538381, 79.30540601961694, 84.53398911196376, 84.25637338417407, 84.26545460545795, 85.4836420784203, 87.91352696902639, 90.17661430338077, 92.00861713262799, 93.01548575895579, 98.76203423385817, 98.9727783538802, 99.79794201276127, 107.09747800437701, 108.13651163607904, 108.93321779444798, 110.0250402418677, 110.0016378863879, 111.22765677992247, 111.25237468431668, 111.39384478448005, 111.46547533826225, 111.19335246869042, 113.40382652607758, 109.88783560648146, 111.17394464251475, 105.79305085720786, 103.86954084162225, 104.94549471311109, 105.1529752173914, 103.18862303071501, 103.6219184508084, 99.27024420143847, 99.38443912679702, 99.72645818929743, 100.12449588951272, 98.61194192862024, 98.94328498877746, 99.17878358049083, 99.58034111906511, 99.88991143373585, 100.63425123843035, 101.62720567561718, 101.7324382737269, 102.78313950968975, 103.10115711998421, 103.19654826483746, 101.66064890652065, 99.31600621426698, 99.46665917814781, 99.86326224412194, 100.47702269946798],
];
// Standard deviation values for each test for each cipher type
#[rustfmt::skip]
let std = [
// IOC
vec![5.308680989027704, 5.667375631763985, 5.694313798894728, 13.260579533918248, 11.984757411133815, 10.79257479070866, 30.572310727898227, 31.558544737454714, 29.74782738969934, 29.89994326538924, 29.88208511065752, 29.35822519783196, 28.08226621635643, 26.9039080333566, 25.779746133326164, 25.361519327325077, 24.0938676113264, 23.962025251773195, 22.986778975612, 22.391125440078515, 21.48966175559214, 21.282490783890847, 23.54347042752208, 23.007461606196625, 22.470127290989854, 22.46083737495495, 22.335734308833704, 21.842992648276777, 21.328948484495783, 21.091535688925806, 22.299195354005896, 25.908190353299076, 28.944593561190946, 29.745169618465518, 29.257933561385176, 29.082750791306463, 30.850623915322483, 30.60287518561244, 34.297476093091255, 34.227680355121976, 33.83366201274149, 33.47245514291196, 33.71817765378484, 33.61623722921555, 33.457736524441394, 33.268636927786225, 33.02851544389993, 32.57750536753346, 32.27504910819506, 32.13743051685783, 31.774715695273105, 31.510087086693826, 31.226981054709615, 31.603377026081173, 32.43742214300265, 32.313175236942016, 32.10965901476282, 31.723842876476088],
// MIC
vec![8.533991278236769, 10.043040356506669, 17.439157154757144, 16.82555790210858, 16.16121615217979, 16.230451963240196, 29.741448152853764, 30.062596284234733, 29.23740138580327, 29.54660233766479, 29.53382368926579, 29.00066030866581, 27.590340055763647, 26.317777150300664, 25.15941316752966, 24.855997452225257, 23.686568619386563, 23.5916406405896, 22.93555019158269, 22.414814224549804, 21.7384480169051, 21.545250334683658, 30.79532515522551, 30.263306803794528, 29.712302551304163, 29.698674629657724, 29.58218464160349, 28.974380410731627, 28.460703330396065, 28.930375591792483, 29.452862542721594, 32.99125860948086, 35.365857141209815, 36.04265895185155, 35.49549956168278, 35.3973530326696, 39.16783729800053, 38.954092122474634, 44.35645136610544, 44.30151019936478, 43.907937512014314, 43.43051286814049, 43.341481134774355, 43.1081362847172, 42.94097122551156, 42.780962676640435, 42.51922042576992, 42.08153435893655, 41.80032987258826, 41.73588378668358, 41.28882503687574, 41.00562810940659, 40.678912475782326, 40.86959564251542, 41.59819774855028, 41.476573984538206, 41.335399898384686, 40.8348380080039],
// MKA
vec![13.991055169401815, 15.452389583557025, 23.82398679993491, 22.713475890920556, 21.872717115023043, 21.17415876696352, 33.09461966322617, 33.286527687350876, 32.129595805224454, 32.25157290191341, 32.22847434077313, 31.768672782159694, 30.824820610626958, 29.892904866698107, 29.1532389540303, 28.924347610322496, 28.344836086047245, 28.35885612637789, 27.725613202042844, 28.135957829625955, 28.245131975461227, 28.18664971772492, 37.19558962966585, 36.54839690744948, 36.40629045563976, 36.393319492771425, 36.277144227521475, 35.59118836877752, 34.93707125934865, 35.25750181013533, 35.8285721057496, 39.648416352645576, 42.8398534246574, 43.782417319304784, 43.18611262758687, 42.89518681174515, 45.3410963037427, 45.070789440810756, 49.76608721459866, 49.667495312133276, 49.24344653027252, 48.743144033719204, 48.68559607830632, 48.49154293834928, 48.29113864028547, 48.07077542887259, 47.6121260778683, 47.10692872424093, 46.87455847936459, 46.702056922647095, 46.25759655960681, 45.95489254680418, 45.61809077785211, 45.72663423191324, 46.86950066704672, 46.726762902041045, 46.720838005620195, 46.178403222093884],
// DIC
vec![6.374380701643576, 10.550650085243282, 11.139088332346248, 24.542536212887196, 22.48836105470084, 20.753660113073384, 54.68599567859451, 54.96504882482044, 52.316934850569744, 52.53636212963978, 52.54131904063581, 51.64480589473959, 49.48352768105154, 47.467212175865576, 45.51460803972665, 44.82711065797504, 41.92500856314917, 41.72801586527345, 39.964068691849796, 38.59209904882661, 37.180247160514874, 36.64633105549309, 47.42268138200909, 46.373495174576, 45.11509310841256, 45.09366417753029, 44.81388980273301, 43.7451794627698, 42.6048761386319, 41.956928635607646, 43.28658277509104, 51.96721967988105, 68.12588465324798, 69.86368641950219, 68.78556822469461, 68.2340088156565, 71.16357402108716, 70.64034205080692, 77.60262247971954, 77.32471453782193, 76.39712315573028, 75.4970014467089, 75.78986770757673, 75.4414720483136, 75.02535230180914, 74.36292808358235, 73.70104955110625, 72.7807567497918, 72.14283091875814, 71.66670546492499, 70.93148755528364, 70.35258497911363, 69.81052892107405, 70.82541603103546, 73.12762224467807, 72.81584825035263, 72.27276639332383, 71.26751567393251],
// EDI
vec![10.033312134420052, 29.958046661531373, 30.099449444572592, 30.802404693844707, 28.89959143969645, 26.818763487650752, 72.12571291953401, 72.94871872152738, 69.29941079529794, 69.57287534951234, 69.73295720073011, 68.54038003507166, 65.62996948145859, 62.95397104059608, 60.34336188314177, 59.36417349443794, 55.76379480392589, 55.468293931493186, 53.120902719418375, 51.44013252413734, 49.6629451386005, 48.94401917132418, 85.44094304032018, 83.46894271208562, 80.93002817372903, 80.89357359756902, 80.27770484653472, 78.7400631334597, 76.68291196639846, 75.57345072139957, 76.6804426671355, 79.99821139279746, 90.14782174085998, 90.86679118742545, 89.55135516985908, 88.79095474399375, 92.67498722870452, 91.99695628844543, 111.57850977572454, 111.09312083871515, 109.77971996717042, 108.3637997187111, 107.99739245760779, 107.4835366279877, 106.82771897980297, 105.74820948638316, 104.75996529805148, 103.51115777236721, 102.64762235764285, 101.99063315298433, 100.98421485255912, 100.16015862029619, 99.29673153487768, 104.11671758339644, 104.74516746785424, 104.27329541085295, 103.44126174277761, 101.87187652095916],
// LR
vec![4.3968425796827395, 5.370117405269756, 5.916936251794224, 8.505184477106605, 8.087510334129227, 7.685125040713471, 10.767323823785608, 10.760546934069229, 10.679103173073395, 10.706533107113069, 10.700364443640469, 10.504933495516346, 10.120062330451791, 9.661333696227207, 9.264155747111372, 9.21733792325797, 8.7911761736833, 8.780735231346867, 8.605399570461689, 8.446631114931447, 8.22865469849358, 8.134300982885476, 9.510973595170396, 9.340049098560625, 9.211113442131394, 9.209982902748578, 9.186928638734093, 9.057152939885695, 8.932614904538925, 8.9461090971929, 9.111975836764714, 10.16588994068586, 12.252889842915545, 12.566351136537635, 12.411670426663864, 12.351158306986804, 12.658336679095378, 12.629172437892702, 13.623606545359745, 13.615363177710176, 13.456431115070176, 13.30828655770287, 13.312927610137613, 13.284567710467055, 13.25996099412475, 13.218632819127116, 13.166908483517718, 13.066045634318954, 13.013361551014814, 13.026278282352873, 12.920812056097454, 12.826819663671325, 12.808450329289554, 12.954762602223113, 13.315393803133206, 13.275415844510619, 13.16156704668278, 12.994066099522199],
// ROD
vec![12.864915477296675, 16.306469584929406, 25.494371580531723, 21.84469191359163, 21.24425660210987, 20.371658332970583, 18.93625251433673, 18.333726858195973, 17.92225796086549, 17.893576556803943, 17.884235788703418, 17.770476287776443, 17.65190544417208, 17.464321499209156, 17.206756130972906, 17.215373793776056, 16.659989060390977, 16.605405910964816, 16.53751069483528, 16.26734802204365, 15.962344606330639, 15.86648367877209, 17.481004783157125, 17.20405956371664, 17.034560368996182, 17.026908194689252, 16.94352889413489, 17.444213160332257, 17.111205284410655, 17.285151510290635, 17.063092313110204, 16.778032186608495, 16.430791464805043, 16.308534632019384, 16.16814740010101, 16.151282087213634, 16.069649067198803, 16.139098698776746, 16.349591463186847, 16.39628564986302, 16.22824734854789, 16.28205910146983, 16.172395967025572, 16.285854761899994, 16.273657456190435, 16.299175053940992, 16.38557353227291, 16.400240174052467, 16.461700334255873, 17.076192656132633, 17.019371536523238, 16.895954534656365, 16.81467241215781, 16.84763909943035, 16.69261321954289, 16.665844176880004, 16.504105252568085, 16.907102113531362],
// LDI
vec![46.30211529249825, 57.52278258996477, 104.41209624124616, 118.72768927102614, 111.22562034248385, 101.32692632289182, 165.9698982766055, 180.92132546605995, 170.43397571178588, 171.23070782774127, 171.1321540964664, 168.7408071098157, 161.84756465245792, 155.8275740094328, 150.12107063589735, 148.04006686644817, 169.8839298631148, 168.70673061926922, 160.34683434895607, 172.2934875218304, 166.77083813584738, 168.5388196350346, 168.71704925709668, 164.46083921930742, 166.67357846239182, 166.60380750839158, 165.15543768657412, 161.2263493532547, 157.17120108725675, 159.12798642633365, 176.92541428850754, 178.19339745228046, 200.8459481301337, 207.74613383110454, 208.18223057562093, 205.43637450029843, 212.25884185441666, 212.2487156091315, 225.7776538061954, 224.1338988538471, 220.9032952623044, 218.2407462621335, 222.6972195275193, 221.25731268026925, 219.24152659446597, 215.66882713898042, 212.76337205050413, 213.51152521842434, 214.11018095874698, 211.8851668342598, 212.30172701431448, 210.39067997941373, 208.59779683993835, 213.76562694648197, 221.04932153144944, 219.52465680285405, 217.2345225909265, 214.25788446131895],
// SDD
vec![15.458628081948785, 18.876787475939285, 31.267288072683762, 32.985917920458235, 33.38650006849517, 31.632807274499996, 45.28896922561766, 48.59477747558257, 46.146097205064464, 46.323717935713965, 46.28621312556071, 45.678250771982356, 44.22565609782606, 42.83304842221494, 41.42606204582724, 41.074898230667124, 41.8491519963356, 41.670657784147906, 40.02808355544797, 45.937302983557444, 44.35705677594243, 43.959745077230814, 43.17435643896392, 42.21014517903573, 41.40208692439577, 41.39180934068569, 41.12732054814764, 40.34597446351519, 39.60094509022446, 40.93676954820652, 44.837274447773154, 44.65426025314537, 49.66842151047334, 51.20504442378766, 50.82479464235639, 50.244023222011506, 51.76930334404469, 51.50742124774515, 54.53169846858919, 54.21141171822756, 53.5524401533538, 52.987088048464, 53.98526013540356, 53.85198449638374, 53.43543423522061, 52.708282874176, 52.081128404684726, 51.68272611005525, 52.00190794824253, 51.68232961691021, 51.63054158895687, 51.293297757057545, 50.97512496285432, 52.114877703180134, 53.72359221381801, 53.39536649965717, 52.86669441421452, 52.25331653865575],
];
let mut z_score_list = Vec::new();
for (i, cipher_type) in cipher_types.iter().enumerate() {
let mut z_score = 0.0;
for j in 0..9 {
let mut standard_deviation = std[j][i];
// Add a small value to the standard deviation to avoid division by zero errors
if j == 0 {
standard_deviation += 0.001;
}
// If the average for the current attribute and cipher type is 0, use the raw statistic value as the z-score
if average[j][i] == 0.0 {
z_score += cipher_stats[j];
} else {
// Otherwise, calculate the z-score using the formula: (statistic - average) / standard deviation
z_score += ((cipher_stats[j] - average[j][i]) / standard_deviation).abs();
}
}
z_score_list.push((cipher_type.clone(), z_score));
}
z_score_list
}
/// Identifies the most likely cipher types for the given text
///
/// # Arguments
///
/// * `text` - The input text to analyze
/// * `num_results` - The number of top results to return
/// * `highlight_cipher` - Optional cipher type to highlight in the results
///
/// # Returns
///
/// A vector of (cipher_type, score) pairs, sorted by score (lower is better)
///
/// # Examples
///
/// ```
/// use cipher_identifier::identify_cipher::identify_cipher;
///
/// let text = "THEQUICKBROWNFOXJUMPSOVERTHELAZYDOG";
/// let results = identify_cipher(text, 5, None);
/// assert_eq!(results.len(), 5);
/// ```
pub fn identify_cipher(text: &str, num_results: usize, highlight_cipher: Option<&str>) -> Vec<CipherScore> {
use crate::statistical_tests::all_stats::get_all_stats;
// List of cipher types to check
#[rustfmt::skip]
let cipher_types = vec![
"6x6bifid".to_string(), "6x6playfair".to_string(), "Autokey".to_string(), "Bazeries".to_string(),
"Beaufort".to_string(), "CONDI".to_string(), "Grandpre".to_string(), "Grandpre10x10".to_string(),
"Gromark".to_string(), "NihilistSub6x6".to_string(), "Patristocrat".to_string(), "Quagmire I".to_string(),
"Quagmire II".to_string(), "Quagmire III".to_string(), "Quagmire IV".to_string(), "Slidefair".to_string(),
"Swagman".to_string(), "Variant".to_string(), "Vigenere".to_string(), "amsco".to_string(),
"bifid".to_string(), "cadenus".to_string(), "checkerboard".to_string(), "cmBifid".to_string(),
"columnar".to_string(), "compressocrat".to_string(), "digrafid".to_string(), "foursquare".to_string(),
"fractionatedMorse".to_string(), "grille".to_string(), "homophonic".to_string(), "keyphrase".to_string(),
"monomeDinome".to_string(), "morbit".to_string(), "myszkowski".to_string(), "nicodemus".to_string(),
"nihilistSub".to_string(), "nihilistTramp".to_string(), "numberedKey".to_string(), "periodicGromark".to_string(),
"phillips".to_string(), "playfair".to_string(), "pollux".to_string(), "porta".to_string(),
"portax".to_string(), "progressiveKey".to_string(), "ragbaby".to_string(), "redefence".to_string(),
"routeTramp".to_string(), "runningKey".to_string(), "sequenceTramp".to_string(), "seriatedPlayfair".to_string(),
"simplesubstitution".to_string(), "syllabary".to_string(), "tridigital".to_string(), "trifid".to_string(),
"trisquare".to_string(), "twosquare".to_string()
];
// Get statistical test results
let stats = get_all_stats(text);
// Extract the scores needed for cipher identification
let scores = vec![
stats["IoC"],
stats["MIC"],
stats["MKA"],
stats["DIC"],
stats["EDI"],
stats["LR"],
stats["ROD"],
stats["LDI"],
stats["SDD"],
];
// Calculate z-scores for each cipher type
let mut scores = get_cipher(&scores, &cipher_types);
// Sort by score (lower is better)
scores.sort_by(|a, b| {
a.1.partial_cmp(&b.1).unwrap_or(Ordering::Equal)
});
// If a specific cipher type should be highlighted, move it to the top
if let Some(highlight) = highlight_cipher {
if let Some(pos) = scores.iter().position(|(cipher, _)| cipher == highlight) {
let highlighted = scores.remove(pos);
scores.insert(0, highlighted);
}
}
// Return the top N results
scores.into_iter().take(num_results).collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_cipher() {
let cipher_stats = vec![36.5, 48.9, 64.9, 16.5, 17.4, 4.9, 48.1, 279.1, 68.2];
let cipher_types = vec!["6x6bifid".to_string(), "Autokey".to_string()];
let scores = get_cipher(&cipher_stats, &cipher_types);
assert_eq!(scores.len(), 2);
assert_eq!(scores[0].0, "6x6bifid");
assert_eq!(scores[1].0, "Autokey");
}
#[test]
fn test_identify_cipher() {
let text = "THEQUICKBROWNFOXJUMPSOVERTHELAZYDOG";
let results = identify_cipher(text, 5, None);
assert_eq!(results.len(), 5);
}
}