普通视图

发现新文章,点击刷新页面。
昨天以前半日闲

摩尔投票算法(Boyer–Moore majority vote algorithm)

作者 小A
2024年10月30日 14:40

前言

小学编程练习中出现一道题,找出一组数(一定要有一个)中超过一半的数,按正常思路就是遍历一次hash统计,然后按值从大到小排序,这样排在第一的值应该是超过这组数数量的一半的,再取出这个键就是要找的数。

反正现在AI时代,也去AI问了一下,给出了一个算法:摩尔投票算法

介绍

摩尔投票法(Boyer–Moore majority vote algorithm),也被称作「多数投票法」,是一种用来寻找一组元素中占多数元素的常数空间级时间复杂度算法。这一算法由罗伯特·S·博耶和J·斯特罗瑟·摩尔在1981年发表,也是处理数据流的一种典型算法。

其主要思想是通过不同元素之间的抵消来找到可能的主要元素候选者,并在最后验证候选者是否真正满足要求。算法的核心在于通过遍历数组,使用两个变量来记录当前候选的主要元素及其出现的次数。如果当前元素与候选元素相同,则增加计数器;如果不同,则减少计数器。最终剩下的元素即为出现次数超过一半的主要元素。

算法可以分为两个部分:
对抗:分属两个候选人的数量进行两两对抗抵消
计数:计算对抗结果中最后留下的候选人的数量是否有效

算法的具体实现步骤

  1. 初始化两个变量:candidate用于保存候选主要元素,count用于记录候选主要元素出现的次数。初始时,candidate可以是任何数组中的元素,count初始化为0。
  2. 遍历数组中的每个元素:
    如果count等于0,将当前元素设置为候选主要元素candidate,并将count设置为1。
    如果count不等于0,检查当前元素是否等于candidate

    如果相等,将count递增1。
    如果不相等,将count递减1。
  3. 遍历完成后,candidate变量中存储的元素就是数组中的主要元素。

代码

def find_majority_element(nums):
    candidate = None
    count = 0
    
    for num in nums:
        if count == 0:
            candidate = num
            count = 1
        elif num == candidate:
            count += 1
        else:
            count -= 1
    
    return candidate
  •  

1024 程序员节:致敬每一位代码英雄

作者 小A
2024年10月24日 15:15

JjeADHaDSPibUKTIcZhdPZpsxzvGhvCX.png
在这个特别的日子里,我们迎来了 1024 程序员节。1024 不仅仅是一个数字,它是二进制世界的基石,是程序员心中最纯粹的符号。在这个由无数 0 和 1 构成的世界里,每一位程序员都是创造奇迹的英雄。

致敬每一位程序员

程序员,你们是现代社会的筑梦者。你们用一行行代码构建起了我们日常生活中不可或缺的数字世界。从智能手机到智能城市,从在线教育到远程医疗,每一个创新的背后都有你们的身影。你们的智慧和创造力,让这个世界变得更加美好。

代码背后的故事

在这个特别的日子里,让我们回顾一下那些代码背后的故事。每一个通宵达旦的夜晚,每一个调试代码的瞬间,每一个成功的喜悦,都是你们成长的见证。你们的坚持和努力,成就了一个又一个伟大的项目,推动了科技的进步和社会的发展。

未来的无限可能

展望未来,我们有理由相信,程序员们将继续书写更多精彩的篇章。无论是人工智能、大数据、云计算,还是区块链、物联网,你们的探索和创新将引领我们走向更加美好的未来。在这个充满机遇和挑战的时代,你们是最宝贵的财富。

一份小小的祝福

在这个 1024 程序员节,我们想对每一位程序员说一声:节日快乐!感谢你们的辛勤付出和卓越贡献。希望你们在未来的日子里,继续追求卓越,不断创新,为社会带来更多的改变和进步。

提示

休息一下:在这个属于你们的节日里,不妨暂时放下手中的键盘,放松一下身心,享受一下属于你们的时光。
充电学习:技术日新月异,不断学习和提升自己,才能保持竞争力。
团队合作:一个人的力量是有限的,团队的力量是无穷的。与同事们一起交流分享,共同成长。

  •  

Elasticsearch映射

作者 小A
2024年10月9日 14:33

elasticsearch映射相当于mysql中的字段的类型。

映射类型

String类型

text:可分词,不可参与聚合
keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合

Numerical数值类型

基本数据类型:longintergershortbytedoublefloathalf_float
浮点数的高精度类型:scaled_float 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。

Date日期类型

Elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。

空间索引类型

geo_point:地理信息点类型
geo_shape:地理信息多点,线、面等类型

创建映射

以创建一个poi的索引类型为例,通过Restful方式创建:

PUT /poi/_mapping
{
  "properties" : {
    "id" : {
      "type" : "long"
    },
    "category" : {
      "type" : "keyword"
    },
    "name" : {
      "type" : "text"
    },
    "address" : {
      "type" : "text",
      "index": true,
      "analyzer": "ik_max_word",    //指定分词
      "search_analyzer": "ik_smart"  //指定搜索分词
    },
    "location" : {
      "type" : "geo_point"
    },
    "remark" : {
      "type" : "text",
      "index" : false
    },
    "create_time" : {
      "type" : "long"
    }
  }
}

当然也可以在创建索引的同时指定映射:

PUT /aoi
{
  "settings":{
   },
  "mappings":{
     "properties" : {}
  }
}

查看映射

通过Restful方式查看映射结果

GET /poi/_mapping
  •  

xaink更新到 1.5.0

作者 小A
2024年9月27日 11:44

代码一行太长的问题之前就发现了,正常来说一般不会有太长的代码,但总有例外。
这不例外来了,所以更新到1.5.0了,其实就是把white-space:pre;改成white-space:pre-wrap,这个是AI告诉我的。
顺便呢,把CodeHighlighter插件问题修改了下,把SpamLite插件加了个通过来源ip过滤。

  •  

推荐个纯html的online-tools

作者 小A
2024年9月27日 10:54

现在的免费空间很多,还有一些便宜的vps,总想放点东西,当然放了不用动,不用维护的就更好,想来想去工具项目是最好的,在github找了几轮,发现了这个:
https://github.com/emn178/online-tools
我改过后的
https://github.com/awinds/online-tools

Online Tools

该项目我看更新还是比较频繁,而且真正是纯html,没有使用别的框架,所有页面全是html和链接,除了工具的js需要引用外部,这个当真维护起来比较麻烦,好的点是干净,不带框架,界面比较清爽。
作者: emn178@gmail.com

拿来主义

Fork项目后,发现直接部署到根目录不太好使用,因为原项目自带了<base href="/online-tools/">,一顿替换操作。
然后想加个自己的链接进去,发现所有的html页面的sidebar非全局,需要牵一发而动全身,就是所有的html页面你都要加一个链接,这是我不可接受的。

改改改

不想框架那就用原生js脚本了,用脚本加json配置来自动生成sidebar和首页的content

var sidebarData = {
    header : {
        logo : 'images/logo.svg',
        title: 'Online-Tools'
    },
    section: {
        'Hash' : {
            'CRC' : {
                'CRC-16': 'crc16.html',
                'CRC-16 File': 'crc16_checksum.html',
                'CRC-32': 'crc32.html',
                'CRC-32 File': 'crc32_checksum.html',
            },
            'MD' : {
                'MD2': 'md2.html',
                'MD2 File': 'md2_file_hash.html',
                'MD4': 'md4.html',
                'MD4 File': 'md4_file_hash.html',
                'MD5': 'md5.html',
                'MD5 File': 'md5_checksum.html',
            },
            'SHA1' : {
                'SHA1': 'sha1.html',
                'SHA1 File': 'sha1_checksum.html',
            },
            'SHA2' : {
                'SHA224': 'sha224.html',
                'SHA224 File': 'sha224_checksum.html',
                'SHA256': 'sha256.html',
                'SHA256 File': 'sha256_checksum.html',
                'Double SHA256': 'double_sha256.html',
            },
            'SHA2-512' : {
                'SHA384': 'sha384.html',
                'SHA384 File': 'sha384_file_hash.html',
                'SHA512': 'sha512.html',
                'SHA512 File': 'sha512_file_hash.html',
                'SHA512/224': 'sha512_224.html',
                'SHA512/224 File': 'sha512_224_file_hash.html',
                'SHA512/256': 'sha512_256.html',
                'SHA512/256 File': 'sha512_256_file_hash.html',
            },
            'SHA3' : {
                'SHA3-224': 'sha3_224.html',
                'SHA3-224 File': 'sha3_224_checksum.html',
                'SHA3-256': 'sha3_256.html',
                'SHA3-256 File': 'sha3_256_checksum.html',
                'SHA3-384': 'sha3_384.html',
                'SHA3-384 File': 'sha3_384_checksum.html',
                'SHA3-512': 'sha3_512.html',
                'HA3-512 File': 'sha3_512_checksum.html',
            },
            'Keccak' : {
                'Keccak-224': 'keccak_224.html',
                'Keccak-224 File': 'keccak_224_checksum.html',
                'Keccak-256': 'keccak_256.html',
                'Keccak-256 File': 'keccak_256_checksum.html',
                'Keccak-384': 'keccak_384.html',
                'Keccak-384 File': 'keccak_384_checksum.html',
                'Keccak-512': 'keccak_512.html',
                'Keccak-512 File': 'keccak_512_checksum.html',
            },
            'SHAKE' : {
                'SHAKE128': 'shake128/',
                'SHAKE128 File': 'shake128/file/',
                'SHAKE256': 'shake256/',
                'SHAKE256 File': 'shake256/file/',
            },
            'cSHAKE' : {
                'cSHAKE128': 'cshake128/',
                'cSHAKE128 File': 'cshake128/file/',
                'cSHAKE256': 'cshake256/',
                'cSHAKE256 File': 'cshake256/file/',
            },
            'KMAC' : {
                'KMAC128': 'kmac128/',
                'KMAC128 File': 'kmac128/file/',
                'KMAC256': 'kmac256/',
                'KMAC256 File': 'kmac256/file/',
            },
            'RIPEMD' : {
                'RIPEMD-128': 'ripemd-128/',
                'RIPEMD-128 File': 'ripemd-128/file/',
                'RIPEMD-160': 'ripemd-160/',
                'RIPEMD-160 File': 'ripemd-160/file/',
                'RIPEMD-256': 'ripemd-256/',
                'RIPEMD-256 File': 'ripemd-256/file/',
                'RIPEMD-320': 'ripemd-320/',
                'RIPEMD-320 File': 'ripemd-320/file/',
            },
            'BLAKE' : {
                'BLAKE2b': 'blake2b/',
                'BLAKE2b File': 'blake2b/file/',
                'BLAKE2s': 'blake2s/',
                'BLAKE2s File': 'blake2s/file/',
                'BLAKE3': 'blake3/',
                'BLAKE3 File': 'blake3/file/',
            },
        },
        'Cryptography' : {
            'AES': {
                'Encryption': 'aes/encrypt/',
                'Decryption': 'aes/decrypt/',
            },
            'DES': {
                'Encryption': 'des/encrypt/',
                'Decryption': 'des/decrypt/',
            },
            'Triple DES': {
                'Encryption': 'triple-des/encrypt/',
                'Decryption': 'triple-des/decrypt/',
            },
            'RC4': {
                'Encryption': 'rc4/encrypt/',
                'Decryption': 'rc4/decrypt/',
            },
            'ECDSA': {
                'Key Generator': 'ecdsa/key-generator/',
                'Sign Message': 'ecdsa/sign/',
                'Verify Signature': 'ecdsa/verify/',
            },
            'RSA': {
                'Key Generator': 'rsa/key-generator/',
                'Sign Message': 'rsa/sign/',
                'Verify Signature': 'rsa/verify/',
                'Encryption': 'rsa/encrypt/',
                'Decryption': 'rsa/decrypt/',
            },
        },
        'Encoding' : {
            'Hex (Base16)': {
                'Encode': 'hex_encode.html',
                'Decode': 'hex_decode.html',
                'File to Hex': 'hex_encode_file.html',
                'Hex to File': 'hex_decode_file.html',
            },
            'Base32': {
                'Encode': 'base32_encode.html',
                'Decode': 'base32_decode.html',
                'File to Base32': 'base32_encode_file.html',
                'Base32 to File': 'base32_decode_file.html',
            },
            'Base58': {
                'Encode': 'base58/encode/',
                'Decode': 'base58/decode/',
                'File to Base58': 'base58/encode/file/',
                'Base58 to File': 'base58/decode/file/',
            },
            'Base64': {
                'Encode': 'base64_encode.html',
                'Decode': 'base64_decode.html',
                'File to Base64': 'base64_encode_file.html',
                'Base64 to File': 'base64_decode_file.html',
            },
            'HTML': {
                'Encode': 'html_encode.html',
                'Decode': 'html_decode.html',
            },
            'URL': {
                'Encode': 'url_encode.html',
                'Decode': 'url_decode.html',
            },
        },
        'Format' : {
            'JSON': {
                'Validator': 'json/validator/',
                'Minifier': 'json/minifier/',
                'Formatter': 'json/formatter/',
                'Viewer': 'json/viewer/',
            },
            'XML': {
                'Validator': 'xml/validator/',
                'Minifier': 'xml/minifier/',
                'Formatter': 'xml/formatter/',
            },
        },
        'Convert' : {
            'Case': {
                'lower case': 'case/lower/',
                'UPPER CASE': 'case/upper/',
                'lowerCamelCase': 'case/lower-camel/',
                'UpperCamelCase': 'case/upper-camel/',
                'snake_case': 'case/snake/',
                'kebab-case': 'case/kebab/',
                'CONSTANT_CASE': 'case/constant/',
            },
        },
        'Others' : {
            'Others': {
                'QR Code Generator': 'qr-code/generator/',
                'Syntax Highlight': 'syntax-highlight/',
            },
        },
        'Links' : {
            'link': {
                'Contact': 'https://github.com/emn178/online-tools/issues',
            },
        },
    }
};



function loadIndex() {
    var html = '';
    for (var section in sidebarData.section) {
        if(sidebarData.section[section]['link']) {
            continue;
        }
        html += '<div class="section">';
        html += '<h2>'+section+'</h2>';
        html += '<div class="blocks">';
        for (var detail in sidebarData.section[section]) {
            html += '<div class="block">';
            html += '<h3>' + detail + '</h3>';
            html += '<nav>';
            html += '<ol>';
            for (var item in sidebarData.section[section][detail]) {
                var url = sidebarData.section[section][detail][item];
                html += '<li><a href="' + url + '">' + item + '</a></li>';
            }
            html += '</ol>';
            html += '</nav>';
            html += '</div>';
        }
        html += '</div>';
        html += '</div>';
    }
    document.getElementById('index').innerHTML = html;
}

function loadSidebar(summary = '',nav = '') {
    var html = '';
    html = '<div class="mask"></div>';
    html += '<div class="container">';
    html += '<header>';
    html += '<a href="./"><img src="'+ sidebarData.header.logo +'" width="18" height="18" alt="Logo" title="'+ sidebarData.header.title +'">';
    html += '<h2>'+ sidebarData.header.title +'</h2></a>';
    html += '<div class="toolbar">';
    html += '<button class="icon theme">';
    html += '<img class="light" src="images/light.svg" alt="Dark mode" title="Dark mode">';
    html += '<img class="dark" src="images/dark.svg" alt="Dark mode" title="Dark mode">';
    html += '</button>';
    html += '</div>';
    html += '</header>';

    html += '<section>';
    for (var section in sidebarData.section) {
        html += '<div class="section">';
        html += '<h3>'+section+'</h3>';
        if(sidebarData.section[section]['link']) {
            html += '<nav class="links">';
            html += '<ol>';
            for (var item in sidebarData.section[section]['link']) {
                var url = sidebarData.section[section]['link'][item];
                html += '<li><a href="'+url+'" target="_blank">'+item+'</a></li>';
            }
            html += '</ol>';
            html += '</nav>';
        }
        else {
            for (var detail in sidebarData.section[section]) {
                if (detail == summary) {
                    html += '<details class="active" open>';
                } else {
                    html += '<details>';
                }
                html += '<summary>' + detail + '</summary>';
                html += '<nav>';
                html += '<ol>';
                for (var item in sidebarData.section[section][detail]) {
                    var url = sidebarData.section[section][detail][item];
                    if (nav == item) {
                        html += '<li  class="active">';
                    } else {
                        html += '<li>';
                    }
                    html += '<a href="' + url + '">' + item + '</a></li>';
                }
                html += '</ol>';
                html += '</nav>';
                html += '</details>';
            }
        }
        html += '</div>';
    }
    html += '</section>';
    html += '</div>';
    document.getElementById('sidebar').innerHTML = html;
}

function getSummaryNav(path) {
    for (var section in sidebarData.section) {
        for (var detail in sidebarData.section[section]) {
            for (var item in sidebarData.section[section][detail]) {
                if (sidebarData.section[section][detail][item] == path) {
                    return {
                        summary: detail,
                        nav: item
                    }
                }
            }
        }
    }
    return {
        summary: '',
        nav: ''
    };
}

const url = new URL(window.location.href);
const path = url.pathname.substring(1);
var autoNav = getSummaryNav(path);
//loadSidebar
loadSidebar(autoNav.summary,autoNav.nav);
//loadIndex
if(path == '' || path == 'index.html') {
    loadIndex();
}

然后再每个页面增加<script src="js/sidebar. js"></script>,以后加功能,加链接就改sidebarData就行了,主页的所有功能section也通过js生成了,每个页面里的id=sidebar里的内容可以删除掉了。

部署

因为改成了<base href="/">,所以不适合部署的二级目录,但是可以部署二级域名。就像我部署的:https://tool.bee.la

  •  

分类目录过多的时候控制显示数和更多下拉

作者 小A
2024年9月14日 10:23

说实话一般自己写个博客,怎么会搞那么多分类呢,因为分类一般全部显示,几十个分类的时候就会把页面撑爆,正常就4~5个分类,可以就有一好友(https://www.lknc.vip/)就会去试,试完了还要我改,本来我是拒绝的,但这个事知道了就很闹心,抽时间就给改了,不完美,但可用。

顺便把文章导读高亮时默认的绿色改成了系统蓝色,再把评论下增加了没有评论时:等风等雨等你来

  •  

惠州海之旅

作者 小A
2024年9月9日 10:10

准备

暑假期间就准备去一趟海边,怎耐暑假到哪都是人,而且订房难订没优惠。所以等到开学后全国的学生都回去上学了再去一次海边,这样人比较少,开学后也会便宜很多,约上几个好友,订好了惠州海边大别墅。
各自下单准备好了食材,水果,零食等,带上游戏机,准备去过一个愉快的周末。

担心

9月3日,台风“摩羯”来了,看路径正好周末点路过惠州、深圳,而且不好退房,东西也已经买好了。接连几天狂风大雨,9月6日周五暴雨预警中小学都放假了,各景区全部停业。
好在台风往南移了,9月6日海南登陆,擦着深圳过去了,但是还是伴随着大雨。
20211218041750907.jpeg

出发

9月7日中午吃过饭后,虽然偶有点阵雨,但台风已经过去了,不影响出行,而且因为大小梅沙景区停业的原因,那一路上全程路况都是绿的,整条路都没几辆车,要不是限速80,可能能开得飞起,那是走得最顺的一次惠深沿海高速。

入住

下午2点,顺利到达别墅,院子够大可以停入几辆车,车停入院子后,东西从车上拿下整理放置。
人到齐后,大家带上小孩一齐前往海边,因为刚刚台风过后,我也为海边会比较凉,结果刚刚好,可以下水。海水比较干净,沙滩沙子也比较细软。
可惜因为台风过后的遗留,天气是一阵晴一阵阴一阵雨的,海边游完后也是在雨中回到了别墅。
20240909095854.jpg

烧烤

海边回去后就开始准备烧烤和晚饭了,自带食材和工具,大家一起齐动手,准备了沙拉水果,凉拌菜,鸡翅鸡块,烤串烤肠,西瓜,小孩们玩游戏,大人们烧烤,烤完围桌聊天。
20240909100113.jpg

回程

食材买的太多了,第二天中午继续烧烤剩下的食材,空气炸锅鸡翅鸡块,直接解决第二天的午饭。
午饭过后清理房间和收拾东西,准备回程。因为来的时候人少,回去的时候人也不多,顺利回家。

最后

一个周末时间短点了,时间长点会更好。期待下次再聚。
20240909100511.jpg

  •  

给主题的分类目录加上图标

作者 小A
2024年9月6日 18:28

有没有发现分类菜单终于和百度显示一个样了,发现了吧!

终于又抽个时间把这个显示给加上了,包括手机显示也加上了。

需要去后台外观配置,为了性能,直接配置svg(大小设置为16*16)。

SVG地址:https://tabler.io/icons
  •  

MySQL中的utf8和utf8mb4

作者 小A
2024年8月30日 15:29

起因

评论中增加了Emoji表情,结果写入的时候报错了,找了半天原因,原来是数据库utf8utf8mb4的区别问题。

区别

  • utf8:通常指的是 utf8(也称为 utf8_general_ciutf8_bin),它支持标准的 Unicode 字符,但不支持四个字节的字符(如 Emoji、某些表情符号和其他复杂字符)。
  • utf8mb4:这是一种扩展的 UTF-8 编码,它可以支持所有 Unicode 字符,包括四个字节的字符(如 Emoji)。

Typecho配置

config.inc.php中数据库参数的配置中有charset的配置,可以配置为utf8utf8mb4

代码判断

在不关心具体数据库的判断中可以直接通过配置中的charset判断是否为utf8mb4

$db = Typecho_Db::get();
$dbconfig = $db->getConfig(Typecho_Db::WRITE);
if($dbconfig['charset'] === 'utf8mb4') {
   return true;
}
return false;

建议

不管是否存储Emoji,建议还是使用utf8mb4编码。

  •  

图片上的坐标格式

作者 小A
2024年8月28日 12:07

有些照片拍摄出来后上面带有坐标,但是坐标格式是有很多种的,以下是常见的几种和解析方法。

第一种

格式:47.14.1885N 102.11.20801E
这样的坐标表示北纬47度14.1885分,东经88度11.20801分,转换成小数度方式如下:
47 + 14.18851 / 60 = 47.236475
102 + 11.20801 / 60 = 102.186800

第二种

格式:经度 104.6015°E 纬度 45.3621°N
这样的坐标就写的很清楚,东经104.6015度 北纬45.3621,直接为小数度单位。

第三种

格式:43°46'46"N 110°10'34"E
这样的坐标标明了度分秒的具体单位, 北纬43度46分46秒,东经110度10分34秒,转换成小数度方式如下:
43 + 46 / 60 + 46 / 3600 = 43.7795
110+ 10 / 60 + 34 / 3600 = 110.1761

第四种

格式:E120 30.437,N23 51.251
这样的前面是东经89度30.437分,后面是北纬23度51.251分,转换成小数度方式如下:
120 + 30.437 / 60 = 120.507283
23 + 51.251 / 60 = 23.854183

  •  
❌
❌