巻取

書いてる内容があってるかはしりません

yumとwgetの鶏卵ごっこ

 ふと思い立って寝ていたサーバを立ち上げて諸々セットアップしようとしたら、yumが入ってない。

makitori@instance:~$ yum -y install telnet telnet-server
-bash: yum: command not found

 なので、yumをインストールしようとしたらwgetをやれとのことだったので、そのとおりやってみると、こんどはwgetがない。

makitori@instance:/usr/local/src$ wget http://vault.centos.org/5.3/os/x86_64/CentOS/yum-3.2.19-18.el5.centos.noarch.rpm
-bash: wget: command not found

 ではwgetをどうやってインストールするのかというと、yumをつかえとのこと。 


 ええ…?
 yumをインストールするにはwgetが必要で、wgetをインストールするにはyumが必要??

【GCP】インスタンスにTeraTermからSSHで繋ぎたい

 GCPで作成したVMに、TeraTermからSSH接続するための公開鍵の置き方


 GCPのComuteEngineでは、「メタデータ」と呼ばれる場所に公開鍵を1つ置いておくと、すべてのVMがその公開鍵を参照してくれるので、1つの秘密鍵であっちこっち繋ぎ放題になって便利。置く場所はこんなかんじ
f:id:makitoriel:20210409002753p:plain


#---
 TeraTerm > [設定] > [SSH鍵生成]をクリック
f:id:makitoriel:20210409003622p:plain:w500


 鍵生成をクリック、(必要であれば秘密鍵パスフレーズを設定して)公開鍵・秘密鍵をそれぞれ任意の場所に保存
f:id:makitoriel:20210409003736p:plain:w500


 公開鍵の中身を開き、書式が「 <protocol> <key-blob> <username@example.com>」となっているもののうち <username@example.com>の部分を、***@gmail.comへ書き換える(GCPのアカウントユーザ)
f:id:makitoriel:20210409003811p:plain:w500


 これを、上記のGCP > メタデータ > SSH認証鍵のところへコピペする(改行を含めないように注意)ことで、ローカルのTeraTermから鍵認証で繋げるようになる。


 TeraTermの [ファイル] > [新しい接続] から開き、接続先ホストを指定&SSH接続を指定してOKボタンを押すとSSH認証の画面が開くので、ユーザ名に「makitori@gmail.com」のmakitoriの部分、パスフレーズには秘密鍵に設定したパスフレーズ(設定していなければ空欄)、「RSA/DSA/ECDSA/ED25519鍵を使う」にチェックをいれて秘密鍵を指定。


#---
 VM内でのSSH公開鍵は、このようになっています。

[makitori@instance ~]$ ls -s ./.ssh
total 4
4 authorized_keys

【VBA】ファイルサーバにフォルダをアップする

 ローカルにあるフォルダを、丸ごとネットワーク上の場所にアップする方法です。
 Pythonのshutl -> treecopyでも出来そうなんですが、できなかったので、VBAのモジュールで作って、「フォルダをコピーする」という部分だけVBAのモジュールとして作成して、Pythonから呼び出す形にしました。


 参考はこちら

 Zドライブに、一時的にアップロード先のフォルダを割り付けて、そこへコピーを行っています。

'VBA Module.xlsm

Option Explicit

Sub CopyDirectory(strSourceFol As String, strDestFol As String)
    
    'ファイルシステムのオブジェクトを作成・セット
    Dim FS As Object
    Dim WSNet As Object

    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set WSNet = CreateObject("WScript.Network")

    'Zドライブにコピー先のフォルダを割り付け
    If FSO.DriveExists("Z") Then WSNet.RemoveNetworkDrive "Z:"
    WSNet.MapNetworkdriver "Z:", strDestFol

    'コピー
    FSO.CopyFolder strSourceFol, "Z:\"
    WSNet.RemoveNetworkDrive "Z:"

    '片付け
    Set FSO = Nothing
    Set WSNet = Nothing

End Sub


Python側はいつものVB呼び出し。

#マクロ呼び出し
import xlwings as xw

def CallMacro()

    #諸設定
    macro_path = './Module.xlsm' #ブック名
    macro_name = 'CopyDirectory' #マクロ名
    source_dir_path = '転送したいフォルダ'
    dest_dir_path = '転送先のフォルダ'

    #マクロ実行
    app = xw.apps.add()
    app.display_alerts = False

    wb = xw.Book(macro_path)
    macro()(source_dir_path, dest_dir_path)

    #片付け
    wb.save() 
    wb.close()
    app.kill()

    return


 EXCEL操作といい、ファイルシステムの操作といい、Windows/Office関連の操作は、PythonよりVBの得意分野なのかもしれない。知らんけど

【4問目】カラオケ【重複なしの選択】

分野別 初中級者が解くべき過去問精選 100 問 の4問目。
問題ページ:パ研杯2019-C


方針
 組み合わせは「重複なし組み合わせ」なので、1問目と同じ考え方。
 「組み合わせ作成->判定」の流れの判定の部分が1問目より少し複雑になっている。


(イメージ図)
f:id:makitoriel:20210214201203p:plain:w300

回答

#Python:重複なしの組み合わせ

#入力処理
n, m = map(int,input().split())

scores=[]
for i in range(n):
    scores.append(list(map(int,input().split())))
    
#--------------------------------------------
ans = 0

#すべての曲の 組み合わせについて(重複なし)
for i in range(m):
    for j in range(i, m):

        cnt = 0
        
        #各生徒の高い方の得点を採用して
        #足し合わせてゆく
        for k in range(n):
            cnt += max(scores[k][i], scores[k][j])
        
        #集計結果が、これまでの最高点であれば、ansを上書き
        if cnt > ans:
            ans = cnt
    
print(ans)

【3問目】ATCoder【尺取法】

分野別 初中級者が解くべき過去問精選 100 問 の3問目。
問題ページ:ABC122-B


方針
 尺取虫メソッド。下記に該当する問題のタイプなら、しゃくとり虫で解ける場合が多い。

 数字の列または文字列があり、
 ・ある条件を満たす最長の区間を求める
 ・ある条件を満たす最短の区間を求める
 ・ある条件を満たす区間の数を求める

 区間の始端iを固定し、「そこを始点とした場合に終端はどこになるか」を、jでカウントアップしながら探す。

f:id:makitoriel:20210214173817p:plain:w300


回答

#----------------------------
#条件判定用の関数をさきにつくっておく
def isACGT(a):
    if a == 'A' or a == 'C' or a == 'G' or a == 'T':
        return True
    
    return False
    
#----------------------------

S = list(input())
cnt = 0
ans = 0

#ここから尺取法。始端をiで固定したとき、
#その始端に対応する終端はどこになるか?

for i in range(len(S)): #すべての始端について
    
    cnt=0
    for j in range(i, len(S)): #その終端を探す

        if isACGT(S[j]):
            cnt += 1
            if cnt > ans:
                ans = cnt
        else:break
            
print(ans)
        

【ARC112-A】A - B = C (エア参加)

問題ページ:ARC112-A

方針

 範囲内のある数につき、その数をAに置いたときに「A - B = C」を成り立たせることができるBとCが、①そもそも存在するのか、②存在するとしたらいくつか、を判定してゆく。


 ①について、「ある数から範囲内の最小の数(L)」を引き算し、引いた結果が「範囲内の最小の数(L)」を超えれば、範囲内の数を組み合わせることで「A - B = C」を成り立たせることができる、といえる。

 ②について、「ある数」ー「範囲内の最小の数」の結果と「範囲内の最小の数」との差に+1をした数が、ある数をAにしたとき、「A - B = C」を成り立たせるBとCの組み合わせの数になる。
f:id:makitoriel:20210213235744p:plain:w500

 これを範囲内の最大の数(R)から初めて1つずつ減らしながら数え上げてゆけばよいのだが、それだとTLEする。なので更に下記の図の考え方を使って計算量を削る。
 つまり、ある数Nについて、その数をAとしたときに「A - B = C」を成り立たせることができるBとCの組み合わせがMであるとき、N-1をAとしたときに「A - B = C」を成り立たせることができるBとCの組み合わせの数はM-1となる。
f:id:makitoriel:20210214013850p:plain:w520

 ある数Nを範囲内最大の数(R)でおいて一回計算し、その結果をcalcとすると、求めるべき応えは「1からcalcまでの整数を足し合わせた数」になる。

AC回答

t=int(input())

for cnt in range(t):

    L, R = map(int, input().split())
    ans = 0
    
    if R - L >= L: #①そもそもA - B = Cが成り立つ組み合わせは存在しうるか
        
        #②あるとしたら、それは幾つか
        calc = R-L-L+1
        ans = (calc+1)*calc/2
            
    print(int(ans))

TLE回答

 ちなみに、計算量を削らずにがん回ししたらLTEした。計算量そんなにあるのね。。。

t=int(input())

for cnt in range(t):

    L, R = map(int, input().split())
    ans = 0
    
    for i in range(R, L-1,-1):
       lif i - L >= L:
            ans += (i-L) - L + 1
    
    print(ans)

【2問目】105【約数列挙・約数の個数】

分野別 初中級者が解くべき過去問精選 100 問 の2問目。
問題ページ:ABC106-B 105


方針
 約数の数を求める方法は、下記の2つ。

 1. 実際に割って約数列:nの約数・約数の個数を求める
 2. エラトステネスの篩もどき:1からnまでの数の約数の数を求める

 1の方法は、単独のnに対して約数のリストを出力する(約数の数は、このリストの長さを取ればいい)。今回の問題はこちらでよいが、もし、多くの数の約数の個数を求めてリスト化する場合は、2のエラトステネスの篩もどきで計算するほうが速そうなので、2つとも書いておく。


 1.実際に割って約数列挙は本当に割り算をしつづけるが、重い。ただし、約数自体のリストが出せるので、約数が必要な場合はこちらを選択する。

#約数列挙
def divisors(n):
    
    dev_a=[]
    dev_b=[]
    i=1
    
    while i*i <= n: #√nを超えるnの約数は、n自身しかない
        if n % i == 0:
            dev_a.append(i)
            
            if i != n//i:
                dev_b.append(n//i)
        i += 1
    
    return dev_a + dev_b[::-1] 

n=int(input())
print(divisors(n))


 2. の素因数分解はエラトステネスの篩の考え方を応用し、約数の個数を出すことに特化する代わりに、一気に複数の数の、それぞれの約数の数をリストで打ち出すことができる。f:id:makitoriel:20210213225555p:plain:w400

#複数の整数について、その約数の数のリストを返す
def num_divisors(n):
    num_dev_list = [0]*(n+1)
    
    for i in range(1, n+1):
        for j in range(i, n+1, i):
            num_dev_list[j] += 1
    
    return num_dev_list
#-----------------------------------

n=int(input())
ans_temp = num_divisors(n)
print(ans_temp[n])


 どちらでも正解になるが、2種類書いたのは、メモとして。
 #素因数から約数を復元もできそうだけど、どれくらい大変なのかな…?