2017年10月

第一步:配置HUSTOJ运行所需要的环境

详情请见
Ubuntu 16.04搭建LAMP开发环境

第二步:更新数据

sudo apt-get update 

第三步:安装svn:

sudo apt-get install subversion 

安装过程中,遇到提示,选择“Y”即可

第四步:下载源代码

sudo svn co https://github.com/zhblue/hustoj/branches/php7/trunk/install hustoj

第五步:跳转到安装目录:

cd hustoj 

第六部:执行安装脚本,自动安装

sudo bash install-interactive.sh

安装过程中需要输入数据库的用户名和密码,遇到提示,输入“Y”即可

第七部:测试

安装完毕后,输入oj安装完毕 输入 http://你的服务器IP/JudgeOnline/,出现如下画面,则证明安装成功
HUSTOJ.png

第八步:设置用户

  • 首先我们先注册一个普通用户
    点击 登录->z注册
    填入信息后,注册即可
  • 设置管理员
    进入数据库

    mysql -u root -p

然后输入数据库的密码
查看所有数据库

show databases;

QQ截图20171022115107.png
使用jol数据库

use jol;

设置管理员

insert into privilege(user_id,rightstr)values('admin','administrator');

admin是你刚才注册的那个用户名
退出数据库exit

注意:先注销掉上次的登录,再进行登录,这样就可以有管理后台的权限了。

第九步:启动判题机

sudo judged

第十步:安装 pascal 和 java 编译器

hustoj 安装完默认只能判 c 和 c++代码

sudo apt-get install default-jdk
sudo apt-get install fpc

第一步:更新源

sudo apt-get update

第二步:安装vim编辑器

sudo apt-get install vim

遇到提示,选择"Y"即可

第三步:安装Apache

sudo apt-get install apache2

遇到提示,选择"Y"即可
安装结束后,通过ifconfig产看本机ip,如图:
QQ截图20171022100857.png

然后在浏览器中输入ip,出现以下画面则证明安装成功
Apache2 Ubuntu Default Page_ It works.png

第四步:安装MySQL

sudo apt-get install mysql-server mysql-client

遇到提示,选择"Y"即可,在安装过程中需要输入root用户的密码,输入两次
安装结束后输入:mysql -u root -p然后输入你的root密码,回车后出现如下画面,则证明成功:
QQ截图20171021121339.png

输入exit退出mysql

第五步:安装PHP

sudo apt-get install php7.0

遇到提示,选择"Y"即可,输入php7.0 -v出现以下画面则证明成功
QQ截图20171021121629.png

第六步:安装其他模块

  1. 使得Apache能够解析PHP,php可以操纵数据库

    sudo apt-get install libapache2-mod-php7.0
    sudo apt-get install php7.0-mysql

  2. 重启服务(此过程中需要输入你服务器用户的密码)

    service apache2 restart
    service mysql restart

  3. 测试
  • 更改文件夹权限

    sudo chmod 777 /var/www
    sudo chmod 777 /var/www/html

  • 创建测试文件(vim的使用

    vim /var/www/html/phpinfo.php

    • 文件中写入

      <?php echo phpinfo();?>

  • 用你的浏览器打开:http://你的ip/phpinfo.php,出现PHP一下画面,则郑证明安装成功了

QQ截图20171022103651.png

至此LAMP开发环境安装成功

题目

“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是:

  1. 字符串中必须仅有P, A, T这三种字符,不可以包含其它字符;
  2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
  3. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a, b, c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

现在就请你为PAT写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。
输入格式: 每个测试输入包含1个测试用例。第1行给出一个自然数n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过100,且不包含空格。

输出格式:每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出YES,否则输出NO。

输入样例:
8
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
输出样例:
YES
YES
YES
YES
NO
NO
NO
NO

代码示例及解析

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main{
    static Scanner sc;
    public static void main(String[] args) {
        sc = new Scanner(System.in);
        int a = sc.nextInt();
        if(a<10)//由题意可知,第1行给出一个自然数n (<10),是需要检测的字符串个数。
            arr(a);
        
    }
    //定义一个函数,实现判断
    public static void arr(int f) {
        
        List<String> al = new ArrayList<String>();
        int i=1;
        while(i<=f) {
            String s= sc.next();
            al.add(s);
            i++;
        }
        //输出集合中的所有字符串
        for (String string : al) {
            int a=0,p=0,t=0,p1=0,t1=0;//定义一些变量,用来判别字符个数
            char [] s = string.toCharArray(); //字符串转换成字符数组
            //遍历每个字符数组,判断输出什么
            for (char str : s) {
                /**
                 * 确定只有PAT三个字符,否则直接输出“NO”,同时确定3个位置A的个数
                 * 有题可知P前面吗A的个数乘以PT之间A的个数等于T后面A的个数
                 * p代表P前面Ade个数,t代表PT之间A的个数,a代表T后面A的个数
                 * 所以t*p==a
                 * p1,t2用来判断P和T的个数是不是1
                 */
                if(str=='A'||str=='P'||str=='T') {
                    if('A'==str) {
                        a++;
                    }else if('P'==str) {
                        p1++;
                        p=a;
                        a=0;
                        
                    }else if(('T'==str)&&(p1==1)) {//P必须在T的前面
                        t1++;
                        t=a;
                        a=0;
                        
                    }
                }else {
                    break;
                }
            }
            if((t*p==a)&&(a!=0||p!=0||t!=0)&&(p1==1&&t1==1)) {
                System.out.println("YES");
            }else {
                System.out.println("NO");
            }
            
        }
    }
}

Python实现

#!/usr/bin/python
n = input()
i = 0

str_list = []
while i<n:
    i = i+1
    s = raw_input()
    str_list.append(s)

for item in str_list:
    p = 0
    a = 0
    t = 0
    aa = 0
    ap = 0
    at = 0
    if 'P' not in item or 'A' not in item or 'T' not in item:
        print('NO')
        continue
    for i in item:
        if i not in 'PAT':
            p=a=t=0
            break
        if i == 'A' :
            a=a+1
        elif i == 'P':
            p=p+1
        elif i == 'T':
            t=t+1
        if i == 'A' and p==0 and t==0:
            aa=aa+1
        elif i=='A' and p==1 and t==0:
            ap=ap+1
        elif i=='A' and t==1:
            at=at+1
    if p==1 and a>0 and t==1 and aa*ap==at:
        print('YES')
    else:
        print('NO')

初始化

1.初始化git项目
在要上传的文件夹内,右键鼠标,选择git Bash Here在打开的命令窗口输入以下命令:

git init

回车后将在该文件夹内生成一个.git的隐藏文件夹。
2.在github上创建一个项目
选择New repository
QQ截图20171015085604.png

填入项目的名字与简介,并且勾选Initialize this repository with a README

QQ截图20171015085951.png

点击Create repository完成

点击 Clone or download复制下面的连接
QQ截图20171015090755.png

3.添加远程地址

在与github连接成功后,就需要添加远程地址,从而让我们的本地项目顺利到达对应的仓库,实现远程与本地相连接。
打开终端,输入(把刚才复制的链接替换掉)

git remote add origin git@github.com:yourName/yourRepo.git

初次上传项目

1.将远程仓库与本地库合并

git pull --rebase origin master

2.上传所有

git add .

3.添加注释并上传到缓存区

git commit -m  '本次提交注释'

4.提交并上传代码,第一次提交加上’-u’,强制上传,以后再次提交的时候可以省略。

git push -u origin master

以后上传项目

1.上传所有

git add .

2.添加注释并上传到缓存区

git commit -m  '本次提交注释'

3.提交并上传代码

git push origin master


配置git

1.创建SSH Key
在用户的目录下,打开隐藏文件看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

ssh-keygen -t rsa -C "youremail@example.com"

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,也无需设置密码。
2.将ssh写入github
通过上述命令后将在windows中生成的id_rsa.pub文件,一般在C:\Users\windows用户名.ssh目录下,打开隐藏文件即可看到。复制出来,在github在点击头像,然后点击setting,在找到SSH and GPG keys,创建一个new ssh key,然后将刚刚复制的ssh key填入即可。
QQ截图20171014205505.png

QQ截图20171014205531.png

QQ截图20171014205552.png

3.验证是否连接成功
在终端输入(第一次输入yes)

ssh -T git@github.com

出现如下图所示的证明连接成功了
QQ截图20171014210046.png

4.设置username和email
为了确保上传到自己的github仓库,所以要设置用户名和自己的邮箱,通过以下命令

git config --global user.name "your name"
git config --global user.email "your_email@youremail.com"

题目:

读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。

输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。这里保证n小于10100。

输出格式:在一行内输出n的各位数字之和的每一位,拼音数字间有1 空格,但一行中最后一个拼音数字后没有空格。

输入样例:
1234567890987654321123456789
输出样例:
yi san wu

java参考答案:

    import java.awt.List;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    public class Main {
    
      public static void main(String[] args) {
        int sum = 0;
        
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        //把输入的字符串转换成字符数组
        char ch[] = s.toCharArray();
        //遍历数组
        for (char c : ch) {
          //求和:把字符数组中的字符先转换成字符串,在将字符串转成int类型
          sum += Integer.valueOf(String.valueOf(c));
        }
        //把和转换成字符串,载转换成字符数组
        char ch1[] = String.valueOf(sum).toCharArray();
        //定义一节集合,对应和中每个数字以及要输出的字符串
        Map<Character, String> m = new HashMap<>();
        m.put('0', "ling");
        m.put('1', "yi");
        m.put('2', "er");
        m.put('3', "san");
        m.put('4', "si");
        m.put('5', "wu");
        m.put('6', "liu");
        m.put('7', "qi");
        m.put('8', "ba");
        m.put('9', "jiu");
        //定义一个字符串,方便组拼输出结果(字符串)
        String sums=" ";
        //遍历由和转换的字符串数组
        for (char c : ch1) {
          //组拼字符串
          sums = sums+m.get(c)+" ";
          
        }
        //输出结果,去掉头和尾的空格
        System.out.print(sums.trim());
      }
    
    }

python2参考答案

#!/usr/bin/python
n = input()
l = ['ling', 'yi', 'er', 'san', 'si', 'wu', 'liu', 'qi', 'ba', 'jiu', 'shi']
s = str(n)
sum = 0
for i in s:
    sum += int(i)
sum_str = str(sum)
sum_sum = ''
for index, sum_i in enumerate(sum_str):
    sum_sum = sum_sum+l[int(sum_i)] if index == 0 else sum_sum+' '+l[int(sum_i)]
print sum_sum

创建数据库

package com.itheima.sqlite;


import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyOpenHelper extends SQLiteOpenHelper {
    /**
     * context  上下文
     * name:数据库的名字 
     * factory 目的创建cursor对象   
     * version 数据库的版本   从1开始
     */
    public MyOpenHelper(Context context) {
        super(context, "itheima.db", null,1);
    }

    /**
     * Called when the database is created for the first time.
     * 当数据库第一次创建的时候调用
     * 那么这个方法特别适合做表结构的初始化  创建表就是写sql语句
     */
    public void onCreate(SQLiteDatabase db) {

        db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),phone varchar(20))");
        
    }
    /**
     * Called when the database needs to be upgraded
     * 当数据库版本升级的时候调用 
     * 这个方法适合做   表结构的更新
     */
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        db.execSQL("alter table info add phone varchar(20)");
        
    }

}

利用谷歌封装好的API对数据库进行增删改查

package com.itheima.sqlite;

import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.provider.Contacts.Intents.Insert;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.itheima.crud.R;

public class MainActivity extends Activity {

    private MyOpenHelper myOpenHelper;
    private List<Person> lists;
    private ListView lv;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //[0]找到lv
        
        lv = (ListView) findViewById(R.id.lv);
        
        myOpenHelper = new MyOpenHelper(getApplicationContext());
        
        
        //[1]定义一个集合用来存listview 要展示的数据 
        lists = new ArrayList<Person>();
        
        //打开或者创建数据库  如果是第一次就是创建   
                //SQLiteDatabase sqLiteDatabase = myOpenHelper.getWritableDatabase();
        //打开或者创建数据库  如果是第一次就是创建     如果磁盘满了 返回只读的
                //SQLiteDatabase readableDatabase = myOpenHelper.getReadableDatabase();
    
    }
    //点击按钮增加一条记录
    public void click1(View v){
        //[1]获取数据库对象
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
        //[2]执行增加一条的sql语句 
                //db.execSQL("insert into info(name,phone) values(?,?)", new Object[]{"张三","1388888"});
        /**
         * table 表名  
         * ContentValues 内部封装了一个map   key:  对应列的名字  value对应的值
         */
        ContentValues values = new ContentValues();
        values.put("name", "王五");
        values.put("phone", "110");
        //返回值代表插入新行的id 
        long insert = db.insert("info", null, values); //底层就在组拼sql语句
        //[3]数据库用完需要关闭
        db.close();
        
        if (insert>0) {
            Toast.makeText(getApplicationContext(), "添加成功", 1).show();
        }else {
            Toast.makeText(getApplicationContext(), "添加fail", 1).show();
        }
        
    }
    
    
    //删除
    public void click2(View v){
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
                //db.execSQL("delete from info where name=?", new Object[]{"张三"});
        //返回值代表影响的行数 
        int delete = db.delete("info", "name=?", new String[]{"王五"});
        db.close();

        Toast.makeText(getApplicationContext(), "删除了"+delete+"行", 0).show();
        
    }
    
    //更新 
    public void click3(View v){
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();

               //db.execSQL("update info set phone=? where name=? ", new Object[]{"138888888","张三"});    
        ContentValues values = new ContentValues();
        values.put("phone", "114");
        //代表更新了多少行 
        int update = db.update("info", values, "name=?", new String[]{"王五"});
        db.close();
        
        Toast.makeText(getApplicationContext(), "更新了"+update+"行", 0).show();
    }
    
    
    //查找
    public void click4(View v){
        
        SQLiteDatabase db = myOpenHelper.getReadableDatabase();

        //columns 代表你要查询的列
        //selection 根据什么查询phone 
//        Cursor cursor = db.query("info", new String[]{"name","phone"}, "name=?", new String[]{"王五"}, null, null, null);
        Cursor cursor = db.query("info", null,null, null, null, null, null);

                //Cursor cursor = db.rawQuery("select * from info", null);
        if (cursor!= null&&cursor.getCount()>0) {
            while(cursor.moveToNext()){
                //columnIndex代表列的索引 
                String name = cursor.getString(1);
                String phone = cursor.getString(2);
                
                //把数据封装到javabean
                Person person = new Person();
                person.setName(name);
                person.setPhone(phone);
                
                //把javabena对象加入到集合
                lists.add(person);
                
            }
                    
            
        }
        
        
    }        
}

数据库的创建

定义一个类继承SQLiteOpenHelper

package com.itheima.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyOpenHelper extends SQLiteOpenHelper {
    /**
     * context  上下文
     * name:数据库的名字 
     * factory 目的创建cursor对象   
     * version 数据库的版本   从1开始
     */
    public MyOpenHelper(Context context) {
        super(context, "itheima.db", null,1);        
    }
    /**
     * 当数据库第一次创建的时候调用
     * 那么这个方法特别适合做表结构的初始化  创建表就是写sql语句
     */
    public void onCreate(SQLiteDatabase db) {
        //id 一般以_id 
        db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),phone varchar(20))");
    }
    /**
     * 当数据库版本升级的时候调用 
     * 这个方法适合做   表结构的更新
     */
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("alter table info add phone varchar(20)");
    }

}

安卓利用SQL语句进行增删改查

package com.itheima.sqlite;

import android.os.Bundle;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {
private MyOpenHelper myOpenHelper;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    myOpenHelper = new MyOpenHelper(getApplicationContext());
    //打开或者创建数据库  如果是第一次就是创建   
    //SQLiteDatabase sqLiteDatabase = myOpenHelper.getWritableDatabase();
    //打开或者创建数据库  如果是第一次就是创建     如果磁盘满了 返回只读的
    //SQLiteDatabase readableDatabase = myOpenHelper.getReadableDatabase();
        
}

//点击按钮增加一条记录
public void click1(View v){
    //[1]获取数据库对象
    SQLiteDatabase db = myOpenHelper.getWritableDatabase();
    //[2]执行增加一条的sql语句 
    db.execSQL("insert into info(name,phone) values(?,?)", new Object[]{"小鸣","19189897878"});
    //[3]数据库用完需要关闭
    db.close();
    
}


//删除
public void click2(View v){
    SQLiteDatabase db = myOpenHelper.getWritableDatabase();
    db.execSQL("delete from info where name=?", new Object[]{"小鸣"});
    db.close();
    
}

//更新 
public void click3(View v){
    SQLiteDatabase db = myOpenHelper.getWritableDatabase();

    db.execSQL("update info set phone=? where name=? ", new Object[]{"1910000000","小鸣"});
    
    db.close();
}

//查找
public void click4(View v){
    SQLiteDatabase db = myOpenHelper.getReadableDatabase();
    Cursor cursor = db.rawQuery("select * from info", null);
    if (cursor!= null&&cursor.getCount()>0) {
        while(cursor.moveToNext()){
            //columnIndex代表列的索引 
            String name = cursor.getString(1);
            String phone = cursor.getString(2);
            System.out.println("name:"+name+";phone:"+phone);    
        }
    }
    
    
}

}

附:布局文件
<Button

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="click1"
    android:text="add" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="click2"
    android:text="delete" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="click3"
    android:text="update" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="click4"
    android:text="find" />


在xml布局文件中添加

android:singleLine="true"
android:ellipsize="marquee"
android:focusable="true"

这些属性
即:

    <TextView
    android:id="@+id/textview1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:text="@string/hello_world" />

如果是多个TextView,则需要把定义一个类继承TextView,并且把TextView改成包名+自己定义的类名
代码示例如下:

  <com.sunxiaoning.marqueetextviewdemo.MarqueeText
    android:id="@+id/textview1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:text="@string/hello_world" />
 <com.sunxiaoning.marqueetextviewdemo.MarqueeText
    android:layout_below="@+id/textview1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:text="@string/hello_world" />

同时自定义一个类,继承TextView重写TextView的所有方法和isFocused()方法,使isFocused()的返回值为true

package com.sunxiaoning.marqueetextviewdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;

public class MarqueeText extends TextView{

    public MarqueeTexct(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        
    }

    public MarqueeTexct(Context context, AttributeSet attrs) {
        super(context, attrs);
        
    }

    public MarqueeTexct(Context context) {
        super(context);
        
    }

    public boolean isFocused() {
        return true;
    }

}

final关键字用于修饰类、变量和方法,它有“这是无法改变的”或者“最终”的含义,因此被final修饰的为不能被继承,被final修饰的方法不能被子类重写,final修饰的变量(局部变量和成员变量)是常量,只能赋值一次。

1.final关键字修饰的类

java中的类被final关键字修饰后,该类将不能被继承,也不能够派生子类。为了避免被继承,被子类复写功能。

2.final关键字修饰方法

当一个类的方法被final关键字修饰后,这个类的子类将不能重写改方法。

3.final关键字修饰变量

java中被final修饰的变量(既可以修饰成员变量,有可以修饰局部变量)为常量,它只能被赋值一次,也就是说final修饰的变量一旦被赋值,其值不能改变。

注意:当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成。单词间通过_连接。
注:内部类定义在类中的局部位置上是,只能访问该局部被final修饰的局部变量。