跳转至

Blog

约 45 个字 预计阅读时间不到 1 分钟

命里有时终须有,命里无时莫强求
日出东海落西山,愁也一天,喜也一天
遇事不钻牛角尖,人也舒坦,心也舒坦



最长回文子串

约 623 个字 38 行代码 1 张图片 预计阅读时间 3 分钟

题目链接: 5. 最长回文子串

题解链接:5. 最长回文子串 - 力扣(LeetCode)

中心扩散法

从每一个位置出发,向两边扩散即可。遇到不是回文的时候结束。举个例子,str=acdbbdaa 我们需要寻找从第一个 b(位置为 3)出发最长回文串为多少。怎么寻找?

  1. 首先往左寻找与当期位置相同的字符,直到遇到不相等为止。
  2. 然后往右寻找与当期位置相同的字符,直到遇到不相等为止。
  3. 最后左右双向扩散,直到左和右不相等。如下图所示:

image.png

每个位置向两边扩散都会出现一个窗口大小(cur_len)。如果 cur_len > length(用来表示最长回文串的长度)。则更新 length 的值。

因为我们最后要返回的是具体子串,而不是长度,因此,还需要记录一下 length 时的起始位置(start),即此时还要 start = left。

Python
class Solution:
    def longestPalindrome(self, s: str) -> str:
        if s is None or len(s) == 0:
            return ''
        n = len(s)
        start = length = 0
        for i in range(n):
            left, right, cur_len = i - 1, i + 1, 1
            while left >= 0 and s[left] == s[i]:
                left -= 1
                cur_len += 1
            while right < n and s[right] == s[i]:
                right += 1
                cur_len += 1
            while left >= 0 and right < n and s[left] == s[right]:
                left -= 1
                right += 1
                cur_len += 2
            if cur_len > length:
                length = cur_len
                start = left + 1
        return s[start:start+length]

动态规划

中心扩散的方法,其实做了很多重复计算。动态规划就是为了减少重复计算的问题。动态规划听起来很高大上。其实说白了就是空间换时间,将计算结果暂存起来,避免重复计算。作用和工程中用 redis 做缓存有异曲同工之妙。

我们用一个 boolean dp[l][r] 表示字符串从 i 到 j 这段是否为回文。

试想如果 dp[l][r]=true,我们要判断 dp[l-1][r+1] 是否为回文,只需要判断字符串在 (l-1) 和(r+1) 两个位置是否为相同的字符。

进入正题,动态规划关键是找到初始状态和状态转移方程。

初始状态,l=r 时,此时 dp[l][r]=true。

状态转移方程,dp[l][r]=true 并且 (l-1) 和(r+1) 两个位置为相同的字符,此时 dp[l-1][r+1]=true。

Python
class Solution:
    def longestPalindrome(self, s: str) -> str:
        if s is None or len(s) == 0:
            return ''
        n = len(s)
        start = end = 0
        length = 1
        dp = [[False] * n for _ in range(n)]
        for r in range(n):
            for l in range(r):
                if s[l] == s[r] and (r - l <= 2 or dp[l + 1][r - 1]):
                    dp[l][r] = True
                    if r - l + 1 > length:
                        length = r - l + 1
                        start, end = l, r
        return s[start:end+1]

if s[l] == s[r] and (r - l <= 2 or dp[l + 1][r - 1]): 这个判断条件的含义是

1. s.charAt(l) == s.charAt(r)

这一部分表示:当前字符串左右两端的字符是否相等

  • 如果 s[l] 和 s[r] 不相等,那么从 l 到 r 之间的子串显然不可能是回文串,因此直接跳过后续判断。

  • 如果相等,就进一步判断该子串中间部分是否是回文,从而确定整个子串是否是回文串。

2. (r - l <= 2 || dp[l + 1][r - 1])

这一部分表示:在两种情况下,从位置 l 到 r 的子串可以被确认是回文串

(1) r - l <= 2

如果 r - l <= 2,说明 l 和 r 之间最多只有 0 个或 1 个字符,这种情况下:

  • s[l] == s[r] 就足以判断该子串是回文串了,因为中间的部分要么为空(r - l = 1),要么只有一个字符(r - l = 2)。

  • 示例:对于 aba、aa,只需要两端相等即可确认它们是回文。

(2) dp[l + 1][r - 1]

如果 r - l > 2,说明 l 和 r 之间至少隔着两个字符,那么子串 [l+1, r-1] 是否是回文就变得重要。

  • dp[l + 1][r - 1] 是一个动态规划数组,记录从位置 l+1 到 r-1 的子串是否是回文。

  • 如果 dp[l + 1][r - 1] == true,说明该子串是回文串,再加上 s[l] == s[r],可以确认 [l, r] 也是回文串。

  • 如果 dp[l + 1][r - 1] == false,那么中间部分不是回文,即使两端字符相等,也无法形成回文串。

手撕快速排序

约 267 个字 35 行代码 2 张图片 预计阅读时间 1 分钟

题目连接: 912. 排序数组

代码 (三路快排)

Python
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        self.quick_sort(nums, 0, len(nums) - 1)
        return nums

    def quick_sort(self, nums: List[int], left: int, right: int) -> None:
        if left >= right:
            return
        le, gt = self.partition(nums, left, right)
        self.quick_sort(nums, left, le - 1)
        self.quick_sort(nums, gt, right)

    def partition(self, nums: List[int], left: int, right: int):
        random_index = random.randint(left, right)
        nums[random_index], nums[left] = nums[left], nums[random_index]
        pivot = nums[left]

        # 循环不变量:
        # [left, le - 1] < pivot
        # [le, i] = pivot
        # [gt, right] > pivot
        le = left
        gt = right + 1
        i = left + 1
        while i < gt:
            if nums[i] < pivot:
                nums[i], nums[le] = nums[le], nums[i]
                le += 1
                i += 1
            elif nums[i] == pivot:
                i += 1
            else:
                gt -= 1
                nums[i], nums[gt] = nums[gt], nums[i]
        return le, gt

三路快排

思想:把整个数组分成三个部分,引入两个指针,le (less equal) 和 gt (great than)

image.png

此时有:

  1. nums[left, le - 1] 均小于 V
  2. nums[gt, right] 均大于 V

初始值:

  • le = left
  • gt = right + 1

遍历指针 i 从 left + 1 开始

  1. 遇到比 V 小的,交换 (le, i),le、i 均后移一位
  2. 遇到等于 V 的,不用交换,i 后移一位
  3. 遇到比 V 大的,gt 前移一位,交换 (gt, i)
    • 注意:此时 i 不能后移,因为交换过来的 nums[gt] 之前未看过

现在考虑退出循坏的条件,i 碰到 gt 即可

不要取 "=",因为 i 没看过,表示下一个要看,gt 的值都看过了,故 while i < gt

循环停止时

image.png

此时有:

  1. nums[left, le - 1] 均小于 V
  2. nums[gt, right] 均大于 V
  3. nums[le, gt - 1] 均等于 V

返回 le, gt, 并回到 quick_sort 函数

  • 递归调用左区间 [left, le - 1]
  • 递归调用右区间 [gt, right]
  • 直到排序完成

K 个一组翻转链表

约 138 个字 36 行代码 预计阅读时间 1 分钟

题目链接: 25. K 个一组翻转链表

Python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        '''
        pre 是这次翻转后的头节点
        p0 是上一次翻转的尾节点
        nxt = p0.next 是这次翻转前的头节点/这次翻转后的尾节点
        cur 是下一次翻转前的头节点
        在一次翻转完成之后
        nxt.next = cur 这一次翻转的尾节点应指向下一次的头节点
        p0.next = pre 上次翻转的尾节点应指向这次翻转的头节点
        p0 变为这次翻转后的尾节点
        '''
        n = 0
        cur = head
        while cur:
            cur = cur.next
            n += 1
        p0 = sentinel = ListNode(next=head)
        pre, cur = None, head
        while n >= k:
            n -= k
            for _ in range(k):  
                nxt = cur.next
                cur.next = pre
                pre = cur
                cur = nxt
            nxt = p0.next
            nxt.next = cur
            p0.next = pre
            p0 = nxt
        return sentinel.next

pre 是这次翻转后的头节点

p0 是上一次翻转的尾节点

nxt = p0.next 是这次翻转前的头节点/这次翻转后的尾节点

cur 是下一次翻转前的头节点


在一次翻转完成之后

nxt.next = cur 这一次翻转的尾节点应指向下一次的头节点

p0.next = pre 上次翻转的尾节点应指向这次翻转的头节点

p0 变为这次翻转后的尾节点

01.IdeaGit-Demo

约 198 个字 2 行代码 9 张图片 预计阅读时间 1 分钟

准备

  1. 创建一个github repo

  1. 创建一个idea项目

注意到,github repo中是存在一个预先定义的README文件,而idea项目中不存在

尝试提交并推送

找到左侧commit选项,选中全部并点击Commit

commit完成之后右键master分支,将其改名为main,目的是保证和github repo中的分支保持一致

右键main分支,尝试push

此时还未定义git remote,点击Define remote,复制github repo的链接粘贴进去,再次尝试推送

不出意外,应该要出意外了,idea会提示push reject,代表出现冲突

解决办法如下:

  1. 命令行
Bash
git fetch
git pull --rebase origin main
  1. idea手动拉取

首先进行fetch,然后进行pull

我这里选择命令行执行

此时 push 成功,rt

02.IdeaGit 基础操作

约 1713 个字 26 行代码 31 张图片 预计阅读时间 6 分钟

1. 初始化

Bash
git init

查看目录结构中,就可以看到包含有 .git 子目录,这就说明创建版本库成功

相当于idea中的 vcs----create git repository

2. 将文件添加到版本库

2.1 将文件添加到暂存区

Bash
git add 001.txt        // 添加单个文件到暂存区
git add .                // 将当前目录下所有修改添加到暂存区,除按照规则忽略的之外

相当于idea中的git --> add

不同之处是在idea中即便不进行add,依旧可以commit


2.2 将暂存区文件提交到仓库

Bash
git commit        // 如果暂存区有文件,则将其中的文件提交到仓库
git commit -m 'your comments'         // 带评论提交,用于说明提交内容、变更、作用等

这个和idea中的git -commit一致,不同点:注释必须写


2.3 查看仓库状态

Bash
git status

在idea中,直接在commit界面可以看到改动的所有文件以及未add的文件

红色: 代表未add到暂存区
绿色: 代表已在暂存区但是有修改
无标记:代表无修改


2.4 查看仓库中的具体修改

Bash
git diff    // 查看版本库中所有的改动
git diff 001.txt        // 查看具体文件的改动

在idea中,可以在commit界面中双击文件查看,或者也可以通过右键标签--show diff with working tree查看


2.5 查看历史提交记录

Bash
git log     // 显示所有提交的历史记录
git log --pretty=oneline    // 单行显示提交历史记录的内容

相当于idea中的git窗口,同时commit id 位于右下角


2.6 版本回退

Bash
1
2
3
git reset --hard HEAD^        // 回退到上一个提交版本
git reset --hard HEAD^^        // 回退到上上一个提交版本
git reset --hard 'commit_id'    // 会退到 commit_id 指定的提交版本

如下图,某个git仓库中存在2个提交记录,需要版本回退到第一个记录

输入 git reset --hard f731

此时,如果反悔了,不希望回退,如何重新返回?

输入git log,发现仅存在一条提交记录,查询不到第2条提交记录

可以通过git reflog找到之前的提交记录

Bash
git reflog
git reset --hard 'commit_id'


git工作区域

git reset的方式不仅仅只有hard一种,还有softmixedkeep,而在介绍它们之间的异同前,首先需要理解git的工作区域

  • Workspace: 工作区,就是你平时存放项目代码的地方
  • Index / Stage: 暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息
  • Repository: 仓库区(或版本库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本
  • Remote: 远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换

执行reset命令后还存在文件的区域

git reset


2.6.1 git reset --soft

操作

移动本地库HEAD指针

前置准备(其他演示类似不做过多赘述)

类似上文,某个git仓库中存在2个提交记录,需要版本回退到第一个记录

远程仓库如下图所示

输入下述命令,使用soft回滚,并推送到远程仓库

Bash
git reset --soft 'commitid'
git push --force origin master # 注意这里要强制推送

可以看到远程仓库中第2次提交不存在了,意味着版本库发生修改

运行 git statusll(alias for ls -l), 观察结果可知工作区和暂存区未发生修改

结论

soft只影响版本库,不影响工作区和暂存区


2.6.2 git reset --mixed

操作

移动本地库HEAD指针
重置暂存区

输入下述命令,使用mixed回滚,并推送到远程仓库

Bash
git reset --mixed 'commitid'
git push --force origin master # 注意这里要强制推送

可以看到远程仓库中第2次提交不存在了,意味着版本库发生修改

运行 git statusll(alias for ls -l), 观察结果可知工作区未发生修改,暂存区发生修改(丢失了对t2的追踪)

结论

mixed影响版本库和暂存区,不影响工作区


2.6.3 git reset --hard

操作

移动本地库HEAD指针
重置暂存区
重置工作区

输入下述命令,使用hard回滚,并推送到远程仓库

Bash
git reset --hard 'commitid'
git push --force origin master # 注意这里要强制推送

可以看到远程仓库中第2次提交不存在了,意味着版本库发生修改

运行 git statusll(alias for ls -l), 观察结果可知工作区发生修改,暂存区发生修改(丢失了对t2的追踪)

结论

hard影响版本库、暂存区和工作区


2.6.4 git reset --keep

操作

移动本地库HEAD指针
重置暂存区
重置工作区, 保留改动

keep模式和hard模式有些类似,但是对工作区的操作有些不同,具体如下

工作区中文件如果当前版本和退回版本之间没有发生过变动,则工作区的修改保持不便;如果发生了变动,并且工作区也进行了修改,需要自行合并(或者冲突解决)

1. 工作区文件未发生变动

Bash
git reset --keep 'commitid'

hard模式保持一致,版本库、暂存区和工作区均发生修改

2. 工作区文件发生变动

reset之前,将t1文件中的111改为311,并添加到暂存区

执行reset

Bash
git reset --keep 'commitid'

神奇的是,加入暂存区的对应文件发生的变动也被保留了下来

再来看变动的另一种情况,在reset之前,将t1文件中的111改为311,且将t2文件中的222改成322,并添加到暂存区

执行 reset

Bash
git reset --keep 'commitid'

发现出现报错,原因是f731版本中t2文件是不存在的,导致无法merge

结论

keep影响版本库、暂存区和工作区,可以撤销提交而不丢失文件的更改


接下来学习idea git中的版本回退

首先在项目中创建一个名为 GitResetTest.java 的文件

添加到暂存区并提交

修改文件,再次提交

右键希望回退到的版本,选择Reset

选择hard模式

如果希望撤销回滚,同样需要查询reflog, 打开terminal输入git reflog, 找到对应的commitid

通过右键项目的reset head进行回退


2.7 撤销修改

Bash
git checkout -- 004.txt   // 如果 004.txt 文件在工作区,则丢弃其修改
git checkout -- .            // 丢弃当前目录下所有工作区中文件的修改

idea中:

注意到在rollback右侧有一个静默搁置按钮

点击之后修改的代码也会消失,这个功能主要是用于暂存你修改后的代码,并把你工作区的代码回滚到最后commit的记录,恢复的时候通过:

那么这个操作具体使用场景是什么呢?

试想一下,在我们开发的时候,正在写某个需求的代码,然而此时项目经理要求你去做一个更加重要/紧迫的任务,那么现在这部分需求代码暂未写完,是不能提交的,此时就可以使用静默搁置,将代码暂时搁置,等到把项目经理的任务忙完后,选择取消静默,接着写即可


2.8 删除文件

在被 git 管理的目录中删除文件时,可以选择如下两种方式来记录删除动作:

  1. rm + git commit -am "abc"
  2. git rm + git commit -m "abc"

区别在于

  • 如果文件已经被git跟踪,那么 1、2 都可以正常工作
  • 如果文件未被git跟踪
    • rm + git commit -am "abc" 不会提交删除
    • git rm + git commit -m "abc" 可以确保文件删除被git记录并提交

03.IdeaGit 远程仓库

约 149 个字 5 行代码 2 张图片 预计阅读时间 1 分钟

1. 克隆仓库

Bash
git clone 你的仓库地址

idea中即创建项目的时候选择 from version control

2. 添加远程仓库

Bash
git remote add origin 你的仓库地址

3. 查看远程仓库信息

Bash
git remote [-v] // 显示远程仓库信息

idea中

4. 推送本地内容到远程仓库

Bash
git push -u origin <branch>

-u 代表设置上游分支。

在执行 git push -u origin <branch> 后,Git 会将当前本地分支与远程仓库的 <branch> 分支关联。之后,你可以简单地使用 git pushgit pull,Git 会知道应该推送/拉取哪个远程分支,而不需要每次都指定远程分支的名称。

5. 修改本地仓库对应的远程仓库地址

Bash
git remote set-url origin url

04.IdeaGit 分支管理

约 1063 个字 29 行代码 25 张图片 预计阅读时间 4 分钟

1. 查看分支

Bash
1
2
3
git branch        // 查看本地分支信息
git branch -v     // 查看相对详细的本地分支信息
git branch -av     // 查看包括远程仓库在内的分支信息

注意:在 git branch 的输出内容中,有一个分支,前面带有 * 号,这标识我们当前所在的分支。

2. 创建分支

分支创建后,新分支基于当前分支。

Bash
git branch dev 

idea 中

3. 切换分支

Bash
git checkout dev

idea:

4. 创建并切换分支

Bash
git checkout -b dev # 新建 dev 分支,并切换到该分支上

5. 合并分支

Bash
git checkout master        # 切换回 master 分支
git merge dev            # 将 dev 分钟中的修改合并回 master 分支

idea:先check out 到指定标签,在把需要合并的标签右键合并即可。

6. 删除分支

Bash
git branch -d dev # 删除 dev 分支

7. 建立本地分支和远程分支的关联

7.1 本地分支存在,远程分支存在,但之间没有关联关系。

Bash
git push -u origin/remote_branch 命令推送。

7.2 本地分支存在,但远程分支不存在。

Bash
git push origin local_branch:remote_branch 

7.3 本地分支存在,远程分支存在,且关联关系已建立

使用 git push 命令进行推送即可

idea中本地push时直接修改远程分支名即可

8. 从远程仓库拉取

通过 git fetchgit pull 来获取远程仓库的内容。

Bash
git fetch origin master    
git pull origin master

git fetchgit pull 之间的区别:

8.1 git fetch

git fetch 是仅仅获取远程仓库的更新内容,并不会自动做合并。

需要先查看更新:

Bash
git log -p FETCH_HEAD

或者拉取到一个其他分支(目前还没见过分支创建)

如果没有问题,再进行合并:

Bash
git merge origin/master

新建一个本地分支,拉取远程到本地temp,查看不同,没问题则合并,合并后删除即可。

Bash
## 在本地新建一个temp分支,并将远程origin仓库的master分支代码下载到本地temp分支;
$ git fetch origin master:temp

## 比较本地代码与刚刚从远程下载下来的代码的区别;
$ git diff temp

## 合并temp分支到本地的master分支;
$ git merge temp

## 如果不想保留temp分支,删除;
$ git branch -d temp

实机演示:

在远程仓库手动修改t1111511, 在本地仓库的t1文件中添加666commit

1. git fetch origin master:temp

2. git diff temp

3. git merge temp

出现冲突,手动解决

选择全部接受(lazygitb),当然也可以只选择某一个hunk

最终commit log如下所示

4. git branch -d temp


8.2 git pull

git pull 在获取远程仓库的内容后,会自动做合并,可以看成 git fetch 之后 git merge

Bash
1
2
3
# 因为存在冲突故git pull会报错,以下命令二选一即可
git pull --no-rebase # merge冲突
git pull --rebase # rebase冲突


8.3 idea 拉取远程仓库

1. 前置准备

本地创建GitPullTest.java并添加f1函数,提交并推送

本地仓库添加f2函数,并提交

远程仓库添加f3函数,并提交


2. git fetch

找到idea上方git菜单,选择fetch (这里仅演示fetch,不演示pull,思想都是一致的)

选择remote下的main分支,查看更改

检查过后发现没有问题,右键remotemain分支,选择mergerebase合并

选择merge,发现出现冲突,需要解决

点击merge按钮,弹出冲突解决页面

左侧为本地仓库代码,右侧为远程仓库代码

有两种方式解决冲突

  1. 左下角 Accept LeftAccept Right,但只能选择一个仓库的代码作为最终合并文件
  2. 屏幕中间的>><<,可以同时保留本地和远程代码,也可以只选择其中一份

这里选择同时保留本地和远程代码

PS: 中间部分可以随意修改/调换位置,但两侧是无法修改的

最终效果如图所示(merge)

如果选择rebase,最终效果如下图所示


8.4 merge与rebase的区别(存在冲突)

merge:rebase

1. merge

  • 保留分支历史(会产生合并提交 merge commit)。
  • 适合多人协作,不会修改历史记录。

2. rebase

  • 不产生合并提交,而是将 feature 分支上的提交重新应用到 main 分支后面。
  • 历史会被重写(提交哈希值改变),适合保持提交历史整洁。

8.5 merge fast-forward(不存在冲突)

Fast-forward 是 Git 中的一种 合并方式,当你执行 git merge 时,如果当前分支没有新的提交(即该分支的 HEAD 没有分歧),Git 会直接将当前分支指向目标分支的最新提交,而不创建额外的合并提交。

什么时候会发生 Fast-Forward

  • 当目标分支没有新的提交,并且当前分支完全处于目标分支的前面(即目标分支是当前分支的祖先),Git 就可以简单地将当前分支 “快进” 到目标分支的最新提交,而不需要创建新的合并提交。

merge ff:rebase

上面的例子中,dev分支为目标分支,feature分支为当前分支

dev分支中不存在新的提交,且feature分支完全处于dev分支之前,此时进行merge将触发fast-forward,效果与rebase一致

05.IdeaGit 杂项

约 220 个字 10 行代码 9 张图片 预计阅读时间 1 分钟

Cherry-Pick

复用04.IdeaGit 分支管理8.3的前置准备

merge过程上略有不同,保留函数f2,去除函数f3

最终效果如下:

Java
public class GitPullTest {

    public void f1() {
        System.out.println("f1");
    }

    public void f2() {
        System.out.println("f2");
    }
}

此时,继续创建函数f4

问题来了,在实现函数f4时,发现其可以使用函数f3的逻辑简化代码

而想要重新获取之前已经放弃的函数f3,可以选中记录后点击cherry-pick按钮进行合并(可能需要解决冲突),之后会对函数f4在主干上重新提交,被抛弃的代码也可以重新获得。

解决冲突后,最终效果如下图所示

Undo Commit,Revert Commit,Drop Commit

undo:revert:drop

Tag

在项目完工准备发布时,可以对最后一个提交打上Tag

注意:push的时候一定要选中左下角Push tags,否则无法生效

查看远端仓库

ArchLinux安装与配置

约 477 个字 33 行代码 5 张图片 预计阅读时间 2 分钟

安装

我是跟着下述教程安装的,体验下来并不难 archlinux 基础安装 | archlinux 简明指南

我个人不是很推荐第一次安装用archinstall,用起来不是很舒服...(看个人吧)

安装成功!系统信息如下:

1f11b2036d0a3e1b5d0790cb4b84588c_720

[解决] grub 找不到 Windows 引导

背景如下:

我的 ArchLinux 安装在一块新买的固态硬盘上,我个人认为是这个原因导致其无法找到 Windows Boot,即 运行命令 grub-mkconfig -o /boot/grub/grub.cfg 后,在 grub 界面只能找到 ArchLinux 引导但没有 Windows

排查流程如下:

运行命令 fdisk -l 查找 WindowsEFI 分区

cd3acee020854d26b7e41660c946db16

观察到 WindowsEFI分区位于 /dev/nvme0n1p1 目录下

运行命令 mount /dev/nvme0n1p1 /mntWindows EFI 挂载到 /mnt

运行命令 lsblk 查看是否正确挂载

1abbd9d2c00c07c241ddeca5f2a668f9

运行命令 os-prober 发现 Windows 引导

运行命令 grub-mkconfig -o /boot/grub/grub.cfg 生成 grub 配置文件

e7aa8d1ce4ebc6e5e972a16b405b71f3

最后grub 成功发现 Windows 引导,问题成功解决!!!

安装NVIDIA显卡驱动

查看显卡

Bash
lspci -k | grep -A 2 -E "(VGA|3D)"

安装驱动

Bash
sudo pacman -S nvidia nvidia-utils nvidia-settings
Bash
sudo nvim /etc/default/grub

GRUB_CMDLINE_LINUX中添加nvidia_drm.modeset=1

Bash
sudo grub-mkconfig -o /boot/grub/grub.cfg
Bash
sudo nvim /etc/mkinitcpio.conf

MODULES中加入nvidia nvidia_modeset nvidia_uvm nvidia_drm

kmsHOOKS中去掉

Bash
sudo mkinitcpio -P

reboot 重启

nvidia-smi 验证是否安装成功

安装Hyprland

Bash
1
2
3
4
sudo pacman -S hyprland kitty waybar
sudo pacman -S sddm
sudo pacman -S ttf-jetbrains-mono-nerd adobe-source-han-sans-cn-fonts adobe-source-code-pro-fonts
sudo systemctl enable sddm
Bash
1
2
3
4
5
6
7
vim ~/.config/hypr/hyprland.conf
#添加NVIDIA环境变量
env = LIBVA_DRIVER_NAME,nvidia
env = XDG_SESSION_TYPE,wayland
env = GBM_BACKEND,nvidia-drm
env = __GLX_VENDOR_LIBRARY_NAME,nvidia
env = WLR_NO_HARDWARE_CURSORS,1

执行完上述命令且无报错后,reboot 重启

以下是 Hyprland 的基本操作

  • Win+Q 开启终端
  • Win+C 关闭窗口
  • Win+R 呼出菜单
  • Win+数字 切换桌面
  • Win+Shift+数字 将当前窗口移动到对应工作区
  • Win+鼠标左键 拖动窗口
  • Win+鼠标右键 调整窗口大小
  • Win+V 让窗口浮动出来

安装基础组件

  1. 安装输入法
Bash
1
2
3
4
5
sudo pacman -S fcitx5-im # 输入法基础包组
sudo pacman -S fcitx5-chinese-addons # 官方中文输入引擎
sudo pacman -S fcitx5-anthy # 日文输入引擎
sudo pacman -S fcitx5-pinyin-moegirl # 萌娘百科词库。二刺猿必备(archlinuxcn)
sudo pacman -S fcitx5-material-color # 输入法主题

通过 vim 创建并编辑文件 ~/.config/environment.d/im.conf

Bash
vim ~/.config/environment.d/im.conf

在文件中加入以下内容并保存退出

Text Only
1
2
3
4
5
6
# fix fcitx problem
GTK_IM_MODULE=fcitx
QT_IM_MODULE=fcitx
XMODIFIERS=@im=fcitx
SDL_IM_MODULE=fcitx
GLFW_IM_MODULE=ibus
  1. 配置输入法
Bash
fcitx5-configtool
  1. 安装paru
Bash
1
2
3
git clone https://aur.archlinux.org/paru.git
cd paru
makepkg -si
  1. 安装代理
Bash
paru -S clash-verge-rev
  1. 安装rofi
Bash
sudo pacman -S rofi
  1. 安装google和vscode
Bash
paru -S google-chrome
sudo pacman -S code
  1. 配置声音
Bash
sudo pacman -S pavucontrol-qt
pavucontrol-qt

最终效果

帅!

AstroMailer 🌌

约 509 个字 29 行代码 1 张图片 预计阅读时间 2 分钟

AstroMailer 是一个每日早安邮件发送器,它通过集成 NASA 天文每日一图(APOD)、词霸金句和百度翻译 API,为用户带来浪漫、温暖的早安邮件。

github地址: AstroMailer

功能概述

  • 📧 每日发送早安邮件
    • 附带 NASA 天文每日一图及其解释。
    • 包含词霸每日金句(中英双语)。
    • 邮件支持中英文翻译,并使用简洁优雅的 HTML 样式设计。
  • 🌌 随机背景色和样式
    • 邮件中的句子和背景配色采用动态随机生成,让每一天的邮件都有独特的风格。
    • 🔄 缓存机制
    • 使用 diskcache 缓存 NASA 图片和内容,减少重复 API 请求。

项目架构

AstroMailer 的主要功能分为以下模块:

  1. 邮件发送模块
    • 使用 smtplib 实现邮件的发送。
    • 支持 HTML 格式化邮件内容。
  2. API 调用模块
    • 集成 NASA APOD API 获取每日天文图片和描述。
    • 集成百度翻译 API 翻译图片描述为中文。
    • 使用词霸 API 获取每日金句。
  3. 定时任务模块
    • 使用 schedule 实现每天早上 8 点自动发送邮件。
  4. 缓存模块
    • 使用 diskcache 缓存数据,避免频繁调用 API。

运行截图

📧 邮件示例

技术栈

  • 编程语言: Python 3.10+
  • 主要依赖:

    • smtplib: 发送邮件
    • schedule: 定时任务调度
    • diskcache: 本地缓存
    • requests: 调用 API
    • PyYAML: 解析配置文件
  • API:

安装与运行

1. 克隆项目

Bash
git clone https://github.com/Pale-illusions/AstroMailer.git
cd AstroMailer

2. 创建虚拟环境并安装依赖

Bash
1
2
3
4
5
6
7
8
9
# 创建虚拟环境
python3 -m venv myvenv

# 激活虚拟环境
source myvenv/bin/activate  # macOS/Linux
myvenv\Scripts\activate     # Windows

# 安装依赖
pip install -r requirements.txt

3. 配置环境

resources/config.yaml 文件中配置你的 API 密钥和邮件账户信息。

示例配置文件 config.yaml

YAML
api_key:
  nasa: "你的NASA_API_KEY"
  baidu_translate:
    appid: "你的百度翻译APPID"
    secret_key: "你的百度翻译SECRET_KEY"

email:
  name: "AstroMailer"
  smtp_server: "smtp.gmail.com"
  smtp_port: 587
  sender: "your_email@example.com"
  password: "your_email_password"
  recipients:
    - "recipient1@example.com"
    - "recipient2@example.com"

4. 启动服务

直接运行

Bash
python src/main.py

docker

Bash
docker-compose up -d

贡献指南

欢迎贡献代码!如果你想为 AstroMailer 提交新的功能或修复 bug,请按照以下步骤操作:

  1. Fork 仓库。
  2. 创建新分支:
Bash
git checkout -b feature/your-feature-name
  1. 提交代码并创建 Pull Request。

开源协议

本项目采用 Apache-2.0 license


感谢使用 AstroMailer,让宇宙的浪漫点亮你的每一天!✨