【Gitエラー】「fatal: Out of memory, malloc failed (tried to allocate xxxxxxxxxxx bytes)」の解決方法

原因

ファイル容量の大きいGitリポジトリをチェックアウトしようとしたら起きたので、Gitの解凍処理でメモリが食い尽くされているのが原因らいしい

解決策

解凍処理を小分けにする

~/.gitconfigに以下を追記する

1
2
3
4
5
6
7
8
[core]
packedGitLimit = 128m
packedGitWindowSize = 128m

[pack]
deltaCacheSize = 128m
packSizeLimit = 128m
windowMemory = 128m

自作ソート【Swift】

目的

  • ソートアルゴリズムの基本を身につける
  • Swiftになれる

要件

  • 数字をソートアルゴリズムを使ってソートする(Swiftのソート関数は使わない)
  • 日本語ひらがな、アルファベット小文字の1文字をソートする
  • インプットは数字の場合と、文字の場合がある (ただし、文字と数字の組み合わせはない、どちらか1種類のみの羅列が入力される)
  • 最後に昇順 or 降順の指定がある
  • ユーザーは決まった手順を守るとは限らないので、その場合の例外の対応方法の組み込み (無理矢理処理しても、エラーを返してもいい)k

コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import UIKit

let testValue1:String = "24,6723,23,111,43,1,昇順"
let testValue2:String = "え,い,う,か,と,昇順"
let testValue3:String = "-2,-22347999,あ,2,い,3,-1,ああ,昇順"

enum OrderType:String{
case none = "例外"
case ascending = "昇順"
case descending = "降順"
}

enum ValueType:String{
case Iregular = "例外"
case Number = "数字"
case Charactor = "ローマ字"
case Japanese = "日本語"
}

// ============= メイン処理 ==============
// 入力された文字列を分割
var inputValueList = testValue3.split(separator: ",")

// ソートタイプのチェック
var orderType:OrderType = OrderType(rawValue: String(inputValueList.last ?? "")) ?? OrderType.none

if(orderType == OrderType.none){
print("ソート方法を指定してください")
print("指定がないため、昇順ソートを行います")

orderType = OrderType.ascending
}else{
// ソート指定は邪魔なので取り除く
inputValueList.removeLast()
}

// 入力文字列のタイプを判定
let valueType = CheckValueType(targetValueList: inputValueList)

// ソート処理
var sortedNumberList:Array<Substring> = Array<Substring>()
sortedNumberList = Sort(targetNumberList:inputValueList)

// 何をソートしたか表示
switch valueType {
case .Number:
print(ValueType.Number.rawValue + "ソート完了")
case .Charactor:
print(ValueType.Charactor.rawValue + "ソート完了")
case .Japanese:
print(ValueType.Japanese.rawValue + "ソート完了")
case .Iregular:
print(ValueType.Iregular.rawValue + "ソート完了")
}

// ソートタイプによって出力を切り替え
switch orderType {
case .ascending:
print(sortedNumberList)
case .descending:
print(Array(sortedNumberList.reversed()))
case .none:
print("ソート失敗")
}

// =====================================

// ============== メソッド ===============
// 値のタイプを判定
func CheckValueType(targetValueList:Array<Substring>)-> ValueType{
var retVal : ValueType = ValueType.Iregular
let targetValueCount = targetValueList.count

var numberCount = 0
var charCount = 0
var japaneseCount = 0

// 数字の並びかチェック
for i in 0...inputValueList.count - 1{
let str:Int = Int(inputValueList[i].cString(using: .shiftJIS)!.first!)
if(str >= 48 && str <= 57){ // 数字
numberCount += 1
}else if(str >= 97 && str <= 122){ // 小文字
charCount += 1
}else if(str >= 65 && str <= 90){ // 大文字
charCount += 1
}else if(str == -125){ // ひらがな
japaneseCount += 1
}else if(str == -126){ // カタカナ
japaneseCount += 1
}
}


if(numberCount == targetValueCount){
retVal = ValueType.Number
}else if(charCount == targetValueCount){
retVal = ValueType.Charactor
}else if(japaneseCount == targetValueCount){
retVal = ValueType.Japanese
}else{
retVal = ValueType.Iregular
}

return retVal
}

// ソート処理
func Sort(targetNumberList:Array<Substring>)->Array<Substring>{

var sortList = targetNumberList
var isChange = false

for index in 0...sortList.count - 1{

if(index + 1 == sortList.count)
{
break
}

let firstList = sortList[index].cString(using: .shiftJIS)!
var firstSign = 1
var firstJapaneseSign = 0

let firstCheckValue = firstList.first!
if(firstCheckValue == 45 ) // マイナス符号
{
firstSign = -1
}

if(firstCheckValue == -125 || // ひらがな
firstCheckValue == -126) // カタカナ
{
firstJapaneseSign = Int(firstCheckValue) * -1
}


var first:Int = 0

for fc in firstList{
first += Int(fc) * firstSign
}

if(firstJapaneseSign != 0){
first *= firstJapaneseSign
}


let secondList = sortList[index+1].cString(using: .shiftJIS)!

var secondSign = 1
var secondJapaneseCheckSign = 0

let secondCheckValue = secondList.first!
if(secondCheckValue == 45) // マイナス符号
{
secondSign = -1
}

if(secondCheckValue == -125 || // ひらがな
secondCheckValue == -126) // カタカナ
{
secondJapaneseCheckSign = Int(secondCheckValue) * -1
}
var second:Int = 0

for sc in secondList{
second += Int(sc) * secondSign
}

if(secondJapaneseCheckSign != 0){
second *= secondJapaneseCheckSign
}


let firstValue = sortList[index]
let secondValue = sortList[index+1]

if(first > second)
{
isChange = true

sortList[index] = secondValue
sortList[index + 1] = firstValue
}
}

if(isChange){
sortList = Sort(targetNumberList: sortList)
}

return sortList
}
// =======================================

備考(感想)

  • 文字コード変換する時に全てShiftJISのコードで変換されてしまった(未解決)
  • 今回使ったソートアルゴリズムは「バブルソート」
  • 小数に対応していない

div属性について

dev(devision)要素について

  • dev要素は、複数のブロックに対して、レイアウトを適応させることができる
  • \<dev\>\</dev\>で囲んだブロック全体にレイアウトが適応させる
  • 基本的な概念は内部CSSのclassidと同じ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html>
<head>
<style>
.A{
background:pink;
}
#B{
background:yellow;
}
</style>
</head>
<body>
<!--classを使用-->
<div class="A">
<h1>これは見出しです</p>
<p>これは見出しに対する本文です</p>
</div>

<!--idを使用-->
<div id="B">
<h1>これは見出し2です</p>
<p>これは見出し2に対する本文です</p>
</div>

</body>
</html>

vimのカレントファイルをブラウザで開く

openコマンドを使う

  • vimでは%でカレントファイルのパスを取得できる
  • !はOS用のコマンド(echopwdなど)の先頭につけることでvimエディタ上からOS用コマンドを実行することができる
  • openはファイルのデフォルトで開くソフトに設定されているソフトで開かれる
1
:!open %

入力の手間を減らす

  • これまでのコマンドをショートカットキーで呼び出せるように.vimrcに追記する
1
2
3
4
5
" スペースキーをショートカットのトリガーとして認識するように設定
let mapleader = "\<Space>"

" スペースキー + o で実行できる
nnoremap <Leader>o :!open %<CR>

フォーカスを戻す(Mac)

  • openコマンドを使うとフォーカスがブラウザになってしまうので、AppleScriptを使ってフォーカスをVim(iTerm)に戻す
    • terminal_focusの対象アプリを変更すればiTerm以外のソフトにも対応可能

~/.vim/plugin/BrowserOpen.vim

1
command! -bar BrowserOpen !open % | osascript $HOME/bin/terminal_focus.scpt

~/bin/terminal_focus.scpt

1
tell application "iTerm" to activate

~/.vimrc

1
2
3
4
5
" スペースキーをショートカットのトリガーとして認識するように設定
let mapleader = "\<Space>"

" スペースキー + o で実行できる
nnoremap <Leader>o :BrowserOpen<CR>

AppleScriptでVimの保存時のファイル更新を取得してブラウザを更新する

概要

Vimでファイルを保存した時にファイルをブラウザで開いている場合(HTMLを書いている場合など)、いちいちブラウザにフォーカスを当てて、ブラウザ再読み込みを行うのは面倒くさいので、

  1. ブラウザにフォーカスを当てる
  2. command + rイベントを発行
  3. フォーカスをターミナルに戻す

の動作を自動化する

Vimで使用するコマンドを実装する

  1. /Users/daiki/.vim/pluginchrome.vimを配置
    • ディレクトリがない場合は作成する
  2. 以下のコードをchrome.vimに書き込んで保存

chrome.vim

1
2
3
command! -bar ChromeReload silent !osascript $HOME/bin/chrome_reload.scpt && osascript $HOME/bin/terminal_focus.scpt
command! -bar ChromeStartObserve ChromeStopObserve | autocmd BufWritePost <buffer> ChromeReload
command! -bar ChromeStopObserve autocmd! BufWritePost <buffer>

ブラウザにフォーカスを当ててリロードするコマンドを実装

  1. /Users/daiki/binchrome_reload.scptを配置
    • ディレクトリがない場合は作成する
  2. 以下のコードをchrome_reload.scptに書き込んで保存

    カスタマイズ

  • 1行目:tell application "safari" to activatesafariの部分を別のブラウザの名前に変更すると開くブラウザを変更できる

chrome_reload.scpt

1
2
tell application "safari" to activate
tell application "System Events" to keystroke "r" using {command down}

ターミナルにフォーカスを戻すコマンド

  1. /Users/daiki/binterminal_focus.scptを配置
    • ディレクトリがない場合は作成する
  2. 以下のコードをterminal_focus.scptに書き込んで保存

    カスタマイズ

  • "Terminal"の部分を書き換えると別アプリにフォーカスを当てられる

terminal_focus.scpt

1
tell application "Terminal" to activate

Vimで使用するには

vimを開いて、ブラウザで更新したいファイルに対して以下のコマンドを打つ

  • :ChromeReload:1回ブラウザをリロードする
  • :ChromeStartObserve:Vimで保存するたびにブラウザをリロードする
  • :ChromeStopObserve:ChromeStartObserveの保存時の自動リロードを停止する

参考

https://lukesilvia.hatenablog.com/entry/20101023/p2

Swiftで迷路を解く

目的

  • Swiftの勉強

制作時間

  • 4時間

コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
import UIKit

var targetMaze = [
["#","S","#","#","#","#","#","#","#","#","#"],
["#"," ","#","#","#","#","#","#"," ","#","#"],
["#"," "," "," "," ","#","#"," "," ","#","#"],
["#"," ","#","#"," "," "," "," ","#","#","#"],
["#","#","#","#"," ","#","#","#","#","#","#"],
["#"," "," "," "," ","#"," "," "," ","#","#"],
["#"," ","#","#","#","#"," ","#"," ","#","#"],
["#"," ","#","#","#","#"," ","#"," ","#","#"],
["#"," "," "," "," "," "," ","#"," ","#","#"],
["#","#","#","#","#","#","#","#","G","#","#"]
]

enum MapType:String
{
case Start = "S"
case Goal = "G"
case Wall = "#"
case Root = "+"
}

struct Vec2:Equatable{
var X:Int = 0
var Y:Int = 0
}

struct Direction
{
var Now:Vec2

var Up:Vec2?
var Down:Vec2?
var Right:Vec2?
var Left:Vec2?
}

func CheckRoad(maze:[[String]],pos:Vec2?,beforPos:Vec2,maxPos:Vec2,checkType:MapType)-> Direction?
{
if(pos == nil) {
return nil
}

// 上,右,下,左
var retPos:Direction = Direction(Now:pos!,Up:nil,Down: nil,Right: nil,Left: nil)

// 上下左右の座標を取得
let minusY = retPos.Now.Y - 1
let plusY = retPos.Now.Y + 1
let minusX = retPos.Now.X - 1
let plusX = retPos.Now.X + 1

// マップ内かチェック
if(minusY >= 0){
retPos.Down = Vec2()
}
if(plusY < maxPos.Y){
retPos.Up = Vec2()
}
if(minusX >= 0){
retPos.Left = Vec2()
}
if(plusX < maxPos.X){
retPos.Right = Vec2()
}

// 壁があるかチェック
if(retPos.Down == Vec2() &&
(maze[minusY][retPos.Now.X] != checkType.rawValue) &&
beforPos != Vec2(X: retPos.Now.X, Y: minusY))
{
retPos.Down = Vec2(X:retPos.Now.X,Y:minusY)
}
else{
retPos.Down = nil
}

if(retPos.Up == Vec2() &&
(maze[plusY][retPos.Now.X] != checkType.rawValue) &&
beforPos != Vec2(X: retPos.Now.X, Y: plusY))
{
retPos.Up = Vec2(X:retPos.Now.X,Y:plusY)
}else{
retPos.Up = nil
}

if(retPos.Left == Vec2() &&
(maze[retPos.Now.Y][minusX] != checkType.rawValue) &&
beforPos != Vec2(X: minusX, Y: retPos.Now.Y))
{
retPos.Left = Vec2(X:minusX,Y:retPos.Now.Y)
}else{
retPos.Left = nil
}

if(retPos.Right == Vec2() &&
(maze[retPos.Now.Y][plusX] != checkType.rawValue) &&
beforPos != Vec2(X: plusX, Y: retPos.Now.Y))
{
retPos.Right = Vec2(X:plusX,Y:retPos.Now.Y)
}else{
retPos.Right = nil
}


return retPos
}

// 指定したターゲットの位置を返す
// 見つからなかった場合は、nilが返えってくる
func serchTargetPoint(maze:[[String]],targetMapType:MapType)->Vec2?
{
var retPos:Vec2? = nil

let mazeYCount = maze.count - 1
let mazeXCount = maze[0].count - 1

for Y in 0...mazeYCount
{
for X in 0...mazeXCount{
let checkValue = maze[Y][X]

if(checkValue == targetMapType.rawValue)
{
retPos = Vec2(X:X,Y:Y)
}
}
}

return retPos
}

func printMaze(maze:[[String]]){

let mazeYCount = maze.count - 1
let mazeXCount = maze[0].count - 1

for Y in 0...mazeYCount
{
print("\n")
for X in 0...mazeXCount{
print(maze[Y][X], terminator: "")
}
}

print("\n")
}


printMaze(maze:targetMaze)

let SPos = serchTargetPoint(maze:targetMaze,targetMapType:MapType.Start)
let GPos = serchTargetPoint(maze:targetMaze,targetMapType:MapType.Goal)

print(SPos ?? "スタートなし")
print(GPos ?? "ゴールなし")


let mazeYCount = targetMaze.count - 1
let mazeXCount = targetMaze[0].count - 1

let maxPos = Vec2(X: mazeYCount, Y: mazeXCount)

var RootList:Array<Direction> = Array<Direction>()
RootList.append (CheckRoad(maze:targetMaze,pos: SPos,beforPos: Vec2(X: 0,Y: 0),maxPos: maxPos,checkType: MapType.Wall)!)


var BlackList:Array<Vec2> = Array<Vec2>()

while true {

let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Up ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}


if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Right ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}


if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Down ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}


if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
let direction = CheckRoad(maze:targetMaze,pos: RootList.last?.Left ?? nil,beforPos: RootList.last?.Now ?? Vec2(),maxPos: maxPos,checkType: MapType.Wall)

var checkFlag:Bool = false

for black in BlackList
{
if(black == direction?.Now ?? Vec2())
{
checkFlag = true
}
}

if(GPos == direction?.Now ?? Vec2())
{
break
}

if(direction != nil && !checkFlag)
{
RootList.append(direction!)
}else
{
BlackList.append(RootList.last?.Now ?? Vec2())
if(RootList.count > 0)
{
RootList.removeLast()
}else
{
break
}
}
}
}
}
}

for root in RootList
{
print(root.Now)
targetMaze[root.Now.Y][root.Now.X] = MapType.Root.rawValue
}

printMaze(maze:targetMaze)

感想

  • Enumのコードに値をセットできるので、コードが読みやすい
  • ちょこちょこ出てくる制約に最初はイライラするが、書いているとなれる
  • 制約があるおかげで、コードに統一感が出る

入力補完プラグイン「Deoplete」の導入方法

vimにdeopleteを入れる

インストールに前提条件の多いPluginなので詰まるところが多かった

環境

  • M1 Mac
  • macOS Big Sur(11.2)
  • vim 8.2

公式の手順

日本語訳

最初に

注意: deopleteVimで使用する場合でも Neovim (最新のものを推奨) が必要
Vimを使用する場合Vimバージョン8.1以上 で Python 3.6.1以上timersが有効になっている必要がある。

注意: deopleteはmsgpackパッケージ1.0.0+を必要とします。pipでmsgpackパッケージをインストール/アップグレードしてください。
msgpack/msgpack-python

注意: どうしても古い msgpack を使う必要がある場合は、代わりに deoplete ver.5.2 を使ってください。
Shougo/deoplete.vim

要件

  • neovimをインストールしておく

    1
    pip3 install --user pyvim
  • neovimでpython3が有効かを確認

    • nvimを起動して以下のコマンドで1が出るか確認
      1
      :echo has("python3")

.vimrcに記述

  1. 今回はプラグイン管理ツールのVundleを使用する

    1
    2
    3
    Plugin 'Shougo/deoplete.nvim'
    Plugin 'roxma/nvim-yarp'
    Plugin 'roxma/vim-hug-neovim-rpc'
    1
    2
    " deopleteをVim起動時に有効にする
    let g:deoplete#enable_at_startup = 1
  2. :PluginInstallでインストール

トラブル対応

ファイルを開くとエラーが表示される

1
[deoplete] deoplete failed to load. Try the :UpdateRemotePlugins command and restart Neovim. See also :checkhealth.

VimにPluginマネージャー「Vundle」を入れる

環境

  • Mac MacBook Air (M1, 2020)
  • OS Big Sur v11.0.1
  • VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Oct 29 2020 23:33:57)

手順

1. ホームディレクトリにフォルダを作る

1
mkdir -p ~/.vim/bundle/Vundle.vim

2. GitHubからダウンロード

1
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

3. .vimrcにの先頭に設定を記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set nocompatible
filetype off
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()

Plugin 'VundleVim/Vundle.vim'

" 導入したいプラグインを以下に列挙
" Plugin '[Github Author]/[Github repo]' の形式で記入
Plugin 'airblade/vim-gitgutter'

call vundle#end()
filetype plugin indent on

" その他のカスタム設定を以下に書く

4. vimを開いた状態でコマンドを打ってインストール

1
:PluginInstall

zshとaliasについて

zshとは

  • 読み方: ズィーシェル
  • シェルの一種でbashの進化版

https://ja.wikipedia.org/wiki/Z_Shell

シェルとは

  • カーネルと対話するためのインターフェイス
    • シェルの名前の由来は、カーネルを包み込んでいることに由来する
  • カーネルの中に入力機能を入れない理由
    • シェル(ロジック)とカーネル(インターフェイス)を分けることでインターフェイスを他のカーネルでも使いまわすことができるようになる
    • インターフェイスのエラーでカーネルをクラッシュする可能性を排除できる

https://recruit.cct-inc.co.jp/tecblog/os/shell/

aliasとは

  • シェル上で、長いコマンドや一連のコマンドをまとめて、ひとまとめにすることのできる機能

使い方(zshの場合)

  1. ~/.zshrcに記述する
    1
    alias 別名='本来のコマンド'
  2. 保存して.zshrcLの再読み込みをする
    1
    source ~/.zshrc
  3. 別名で指定したコマンドを打って期待通り動けばOK

使用例

  • 長いパスのフォルダに移動cdしたい場合
    • このコマンドbcを打つだけで記述したcdコマンドが実行される
      1
      alias bc='cd /Users/daiki/Desktop/Blog/Daiki-Iijima.github.io/source/_posts'

複数のコマンドを1つのaliasにまとめる

  • 各コマンドを;で区切ることで連続したコマンドを記述できる
    1
    alias 別名='コマンド1;コマンド2'

    使用例

  • デスクトップへ移動して、testフォルダを生成する
    1
    alias cdmk='cd /Users/daiki/Desktop;mkdir test'

引数を渡す

  • $+数字を本来の引数があるはずの位置に記述することで、引数を渡すことができる
    1
    alias 別名='mkdir $1'
    • 使用する場合
      1
      別名 引数
  • 複数の引数を渡したい場合は、$の後の数字を繰り上げていく
    1
    alias 別名='mkdir $1;mkdir $2'
    • 使用する場合
      1
      別名 引数 引数

使用例